分块笔记

1、分块 (区间加法,查询小于x的个数)

技巧:开vector对区间sort,注意每次暴力更新的区间需要重新把数据放入vector中。

https://loj.ac/problem/6278

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '
'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 50009;
            ll a[maxn];
            ll sum[maxn];
            vector<ll>s[1009];
            int belong[maxn];
int main(){
            int n;  scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
            int block = sqrt(n);
            int num = n/block; if(n%block) num++;
            for(int i=1; i<=n; i++)
            {
                belong[i] = (i-1)/block + 1;
                s[belong[i]].pb(a[i]);
            }
            for(int i=1; i<=num; i++) sort(s[i].begin(),s[i].end());
            int m = n;
            for(int i=1; i<=m; i++){
                int op;scanf("%d", &op);
                if(op == 0){
                    int l,r; ll x;
                    scanf("%d%d%lld", &l, &r, &x);

                     int id = belong[l],le = (belong[l]-1)*block+1;
                     if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++) a[i] += x;
                        s[id].clear();
                        for(int i=le; i<= belong[l]*block; i++) s[id].pb(a[i]);
                        sort(s[id].begin(),s[id].end());
                        continue;
                     }

                     for(int i=l; i<=belong[l]*block; i++) a[i] += x;
                     s[id].clear();
                     for(int i=le; i<= belong[l]*block; i++) s[id].pb(a[i]);
                     sort(s[id].begin(),s[id].end());

                     for(int i=belong[l]+1; i<=belong[r]-1; i++){
                        sum[i] += x;
                     }

                     int rid = belong[r],rle = (rid - 1) * block + 1;
                     for(int i=(rid-1)*block+1; i<=r; i++) a[i]+=x;
                     s[rid].clear();
                     for(int i=rle; i<=min(n, belong[r]*block) ; i++) s[rid].pb(a[i]);

                     sort(s[belong[r]].begin(),s[belong[r]].end());
                }
                else {
                        int l,r; ll x;
                        scanf("%d%d%lld", &l, &r, &x);
                        int cnt = 0;
                        if(belong[l] == belong[r]){
                            for(int i = l; i<= r; i++){
                                if(a[i] + sum[belong[i]] < 1ll*x*x) cnt++;
                            }
                        }
                        else {
                            for(int i=l; i<=belong[l]*block; i++)
                                if(a[i] + sum[belong[i]] < 1ll*x*x) cnt++;
                            for(int i=belong[l]+1; i<=belong[r]-1; i++){
                                cnt += lower_bound(s[i].begin(),s[i].end(), 1ll*x*x-sum[i]) - s[i].begin();
                            }
                            for(int i=(belong[r]-1)*block+1; i<=r; i++)
                                if(a[i] + sum[belong[i]] < 1ll*x*x) cnt++;
                        }
                        printf("%d
", cnt);
                }
            }
            return 0;
}
View Code

2、区间加法,区间查询

开两个标记数组,一个是sum数组,一个是add数组。

https://loj.ac/problem/6280

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '
'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 50009;
            ll a[maxn];
            ll sum[maxn];
            ll add[maxn];
            int belong[maxn];
int main(){
            int n;  scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
            int block = sqrt(n);

            for(int i=1; i<=n; i++)
            {
                belong[i] = (i-1)/block + 1;
                sum[belong[i]] += a[i];
            }

            int m = n;
            while(m--){
                int op; scanf("%d", &op);
                if(op == 0){
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                    if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++){
                            a[i] += x;

                            sum[belong[i]] += x;
                        }
                        continue;
                    }
                    for(int i=l; i <= belong[l]*block; i++){
                        a[i] += x;
                        sum[belong[i]] += x;
                    }
                    for(int i=belong[l]+1; i<=belong[r]-1; i++){
                        sum[i] += block * x;
                        add[i] += x;
                    }
                    for(int i=(belong[r]-1) * block + 1; i<=r; i++){
                        a[i]+=x;
                        sum[belong[i]] += x;
                    }
                }
                else {
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                    ll ans = 0;
                    if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++){
                            ans = (ans + a[i] + add[belong[l]])%(x+1);
                        }
                    }
                    else {
                        for(int i=l; i <= belong[l]*block; i++){
                            ans = (ans + a[i] + add[belong[i]])%(x+1);
                        }
                        for(int i=belong[l]+1; i<=belong[r]-1; i++){
                            ans = (ans + sum[i])%(x+1);
                        }
                        for(int i=(belong[r]-1) * block + 1; i<=r; i++){
                            ans = (ans + a[i] + add[belong[i]]) %(x+1);
                        }
                    }
                    printf("%lld
", ans);
                }

            }
            return 0;
}
View Code

3、区间开方,区间查询

https://loj.ac/problem/6281

由于每个数开方的次数不多,所以暴力去开方就行了,分块记录区间中为0,或1的个数。

这里 变化sum最好写成

sum[belong[i]] -= a[i];
a[i] = sqrt(a[i]);
sum[belong[i]]+=a[i];

/*
int tp = a[j] - sqrt(a[j]);
a[j] = sqrt(a[j]);
sum[belong[j]]-=tp;
*/

上面这个可能有精度问题

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '
'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 50009;
            ll a[maxn];
            ll tot[maxn],sum[maxn];
            int belong[maxn];
int main(){
            int n;  scanf("%d", &n);
            for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
            int block = sqrt(n);

            for(int i=1; i<=n; i++){
                belong[i] = (i-1)/block + 1;
                sum[belong[i]] += a[i];
                if(a[i] == 1 || a[i] == 0) {
                     tot[belong[i]]++;
                }
            }
            int m = n;

            while(m--){
                int op; scanf("%d", &op);
                if(op == 0){
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                    
                    
                    if(belong[l] == belong[r]){
                        for(int i=l; i<=r; i++){
                            if(a[i] == 1 || a[i] == 0) {
                                    continue;
                            }
                            sum[belong[i]] -= a[i];
                            a[i] = sqrt(a[i]);
                            sum[belong[i]]+=a[i];
                            if(a[i] == 1 || a[i] == 0) {
                                    tot[belong[i]]++;
                            }
                        }
                    }
                    else {
                        for(int i=l; i<=belong[l]*block; i++){
                            if(a[i] <= 1) continue;
                             sum[belong[i]] -= a[i];
                            a[i] = sqrt(a[i]);
                            sum[belong[i]]+=a[i];
                            if(a[i] == 1 || a[i] == 0) {
                                    tot[belong[i]]++;
                            }
                        }
                        for(int i=belong[l] + 1; i< belong[r]; i++){
                            if(tot[i] == block)continue;
                            for(int j=(i-1)*block+1; j<=i*block; j++){
                                if(a[j] <= 1) continue;
                                sum[belong[j]] -= a[j];
                                a[j] = sqrt(a[j]);
                                sum[belong[j]]+=a[j];
                            
                                if(a[j] == 1 || a[j] == 0) {
                                        tot[belong[j]]++;
                                }
                            }
                        }
                        for(int i=(belong[r]-1)*block+1; i<=r; i++){
                            if(a[i] <= 1) continue;
                            sum[belong[i]] -= a[i];
                            a[i] = sqrt(a[i]);
                            sum[belong[i]]+=a[i];
                            
                            if(a[i] == 1 || a[i] == 0) {
                                    tot[belong[i]]++;
                            }
                        }
                    }
                }
                else {
                    int l,r,x;
                    scanf("%d%d%d", &l, &r, &x);
                       r = min(r, n);
                    ll res = 0;
                    if(belong[l] == belong[r]) {
                        for(int i=l; i<=r; i++){
                            res += a[i];
                        }
                    }
                    else {
                        for(int i=l; i<=belong[l]*block; i++){
                            res += a[i];
                        }
                        for(int i=belong[l] + 1; i< belong[r]; i++){
                                res += sum[i];
                        }
                        for(int i=(belong[r]-1)*block+1; i<=r; i++){
                            res += a[i];
                        }
                    }
                    printf("%lld
", res);
                }
            }

            return 0;
}
View Code

4、单点插入,单点查询

由于是插入操作,所以用动态容器做插入,比如这题用vector,然后就是由于当一个块插入过多时,可以考虑重新分块。

https://loj.ac/problem/6282

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '
'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 200009;
            int n,block;
            int a[maxn],belong[maxn];
            vector<ll> s[2009];

            void build(){
                int tot = 0;
                for(int i=1; i<=belong[n]; i++) {
                    for(int j=0; j<s[i].size(); j++){
                        a[++tot] = s[i][j];
                    }
                    s[i].clear();
                }
                block = (int)sqrt(tot);
                
                for(int i=1; i<=tot; i++){
                    belong[i] = (i-1) / block + 1;
                    s[belong[i]].pb(a[i]);
                }
            }
int main(){
            scanf("%d", &n);
            for(int i=1; i<=n; i++)
                scanf("%d", &a[i]);
            block = (int)sqrt(n);

            for(int i=1; i<=n; i++){
                belong[i] = (i-1) / block + 1;
                s[belong[i]].pb(a[i]);
            }
            int m = n;
            while(m--){
                int op; scanf("%d", &op);
                if(op == 0){
                    ll l,r,x;
                    scanf("%lld%lld%lld", &l, &r, &x);
                    for(int i=1; i<=belong[n]; i++){
                        if(s[i].size() < l) l -= (ll)s[i].size();
                        else {
                            s[i].insert(s[i].begin() + l -1 ,r);
                            if(s[i].size() > 20 * block) build();
                            break;
                        }
                    }
                }
                else {
                    ll l,r,x;
                    scanf("%lld%lld%lld", &l, &r, &x);

                    for(int i=1; i<=belong[n]; i++){
                        if(s[i].size() < r) r = r - (ll) s[i].size();
                        else {

                            printf("%lld
", s[i][r-1]);
                            break;
                        }
                    }
                }
            }
            return 0;
 }
View Code

5、询问区间等于c的个数,每次询问把区间每个数改为c

https://loj.ac/problem/6284

只要这个块是同一个数,就跳过,否则直接暴力计算并修改。

开了cg【maxn】表示这个块是否统一,统一为这个c,不是就是-1;

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '
'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e4+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/

            const int maxn = 100009;
            int n,block;
            int a[maxn],belong[maxn];
            int cg[maxn];

            void push_down(int id){
                for(int i=(id-1)*block+1; i<=min(n,id*block); i++){
                    a[i] = cg[id];
                }
                cg[id] = -1;
           }
int main(){
            scanf("%d", &n);
            for(int i=1; i<=n; i++)
                scanf("%d", &a[i]);
            block = (int)sqrt(n);

            for(int i=1; i<=n; i++){
                belong[i] = (i-1) / block + 1;
                cg[belong[i]] = -1;
            }
            int m = n;
            while(m--){
                int l,r,c;
                scanf("%d%d%d", &l, &r, &c);
                int tot = 0;
                if(belong [l] == belong [r]){

                    int id = belong[l];
                    if(cg[id] >= 0) push_down(id);
                    for(int i=l; i<=r; i++) {
                        if(a[i] == c) tot++;
                        a[i] = c;
                    }

                }
                else {
                    if(cg[belong[l]]>=0) push_down(belong[l]);
                    for(int i=l; i<=belong[l]*block; i++){
                        if(a[i] == c) tot++;
                        a[i] = c;
                    }

                    for(int i=belong[l]+1; i<belong[r]; i++){
                        if(cg[i] >= 0) {
                            if(cg[i] == c) tot += block;
                            cg[i] = c;
                        }
                        else {
                            for(int j = (i-1) * block + 1; j<= i*block; j++){
                                if(a[j] == c) tot++;
                                a[j] = c;
                            }
                            cg[i] = c;
                        }
                    }
                    if(cg[belong[r]]>=0)push_down(belong [r]);
                    for(int i=(belong[r]-1)*block + 1; i<=r; i++){
                        if(a[i] == c) tot++;
                        a[i] = c;
                    }

                }
                printf("%d
", tot);
            }
            return 0;
 }
View Code

6、不带修改,求区间众数

https://loj.ac/problem/6285

块的大小开30很快。

区间的众数是每个块中的众数中的一个。

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>

using namespace std;
#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "
";
#define pb push_back
#define pq priority_queue



typedef long long ll;
typedef unsigned long long ull;
//typedef __int128 bll;
typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl '
'
//#define R register
#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
#define max3(a,b,c) max(max(a,b), c);
#define min3(a,b,c) min(min(a,b), c);
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 1e9+7;
const double esp = 1e-8;
const double PI=acos(-1.0);
const double PHI=0.61803399;    //黄金分割点
const double tPHI=0.38196601;


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}


/*-----------------------showtime----------------------*/
            const int maxn = 1e5+9;
            int n,blo;
            int a[maxn],val[maxn],be[maxn],cnt[maxn];
            int f[5090][5090];
            vector<int>v[maxn];
            map<int,int>mp;
            void pre(int x){

                memset(cnt, 0, sizeof(cnt));
                int mx = 0;
                int res;
                for(int i=(x-1) * blo + 1; i<=n; i++){
                    int t = be[i];
                    cnt[a[i]]++;
                    if(cnt[a[i]] > mx || (cnt[a[i]] == mx && val[a[i]] < val[res] )){
                        mx = cnt[a[i]];
                        res = a[i];
                    }
                    f[x][t] = res;
                }
            }
            int query(int x,int l,int r){
                return upper_bound(v[x].begin(),v[x].end(),r) - lower_bound(v[x].begin(),v[x].end(),l);
            }
int main(){     
            scanf("%d", &n);
            for(int i=1; i<=n; i++){
                 // scanf("%d", &a[i]);
                 read(a[i]);
            }

            // blo = (int)sqrt(n);
            blo = 30;
            int tot = 0;
            for(int i=1; i<=n; i++){
                be[i] = (i-1)/blo + 1;
                if(!mp.count(a[i])) mp[a[i]] = ++ tot;
                int id = mp[a[i]];
                val[id] = a[i];
                a[i] = id;
                v[id].pb(i);
            }   

            for(int i=1; i<=be[n]; i++){
                pre(i);
            }
            int m = n;
            while(m--){
                int l,r;
                scanf("%d%d", &l, &r);
                int mx = 0,ans;
                for(int i=l; i<=min(r, be[l]*blo); i++){
                    int t = query(a[i], l,r);
                    if(t > mx || (t==mx && val[a[i]] < ans)){
                        ans = val[a[i]];
                        mx = t;
                    }
                }

                int t = query(f[be[l]+1][be[r]-1],l,r);
                if(t > mx || (t==mx && val[f[be[l]+1][be[r]-1]] < ans)){
                        ans = val[f[be[l]+1][be[r]-1]];
                        mx = t;
                }

                if(be[l] < be[r]){
                    for(int i=(be[r]-1)*blo+1; i<=r; i++){
                        int t = query(a[i], l,r);
                        if(t > mx || (t==mx && val[a[i]] < ans)){
                            ans = val[a[i]];
                            mx = t;
                        }
                    }
                }
                printf("%d
", ans);
            }
            return 0;
}
View Code
原文地址:https://www.cnblogs.com/ckxkexing/p/10300122.html