1. 程式人生 > >算法復習——分塊算法

算法復習——分塊算法

arc for -a 每次 max script es2017 打了 空間

題目:

Description

技術分享

Input

技術分享

修正一下

l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

Output

技術分享

Sample Input

6 3
1 2 3 2 1 2
1 5
3 6
1 5

Sample Output

1
2
1

HINT

技術分享


修正下:


n <= 40000, m <= 50000

Source

Vani原創

題解:

技術分享技術分享

題解如上·····一個分塊模板題打了我2個小時·····不得不說代碼能力和專註度還不夠·····另外還學到了節約復雜度和空間的好方法···(具體見getans中的tot是如何每次重新變為1的)

代碼:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=4e4+5;
int visit[N],tim,n,m,num[N],cnt[N][205],ans[205
][205],tot[N],temp[N],id[N],s,idx[N],len,tots,Left[N],Right[N]; bool jud[N]; inline int R() { char c;int f=0; for(c=getchar();c<0||c>9;c=getchar()); for(;c<=9&&c>=0;c=getchar()) f=(f<<3)+(f<<1)+c-0; return f; } inline void pre() { sort(temp+1,temp+n+1
); len=unique(temp+1,temp+n+1)-temp-1; for(int i=1;i<=n;i++) { int t=num[i]; num[i]=lower_bound(temp+1,temp+len+1,num[i])-temp; idx[num[i]]=t; } //離散化------------------------------------------------------- s=(int)sqrt(n); tots=0; for(int i=1;i<=n;i++) { if(i%s==0) id[i]=tots,Right[tots]=i,jud[i]=true; else if(i%s==1) id[i]=++tots,Left[tots]=i; else id[i]=tots; } Right[tots]=n,jud[n]=1; //分塊------------------------------------------------ for(int i=1;i<=n;i++) cnt[num[i]][id[i]]++; for(int i=2;i<=tots;i++) for(int j=1;j<=len;j++) cnt[j][i]+=cnt[j][i-1]; //統計cnt------------------------------------------ for(int i=1;i<=tots;i++) { int maxx=0,anss=1e+8; memset(tot,0,sizeof(tot)); for(int j=Left[i];j<=n;j++) { tot[num[j]]++; if(tot[num[j]]>maxx||(tot[num[j]]==maxx&&num[j]<anss)) maxx=tot[num[j]],anss=num[j]; if(jud[j]==true) ans[i][id[j]]=anss; } } //統計ans------------------------------------------ } inline int getans(int a,int b) { tim++; if(b-a+1<2*s) { int maxx=0,anss=1e+8; for(int i=a;i<=b;i++) { if(visit[num[i]]!=tim) visit[num[i]]=tim,tot[num[i]]=1; else tot[num[i]]++; if(tot[num[i]]>maxx||((tot[num[i]]==maxx)&&num[i]<anss)) maxx=tot[num[i]],anss=num[i]; } return idx[anss]; } else { int lefts,rights; if(a%s==1) lefts=id[a]; else lefts=id[a]+1; if(b%s==0) rights=id[b]; else rights=id[b]-1; int anss=ans[lefts][rights],maxx=cnt[anss][rights]-cnt[anss][lefts-1]; for(int i=a;i<Left[lefts];i++) { if(visit[num[i]]!=tim) visit[num[i]]=tim,tot[num[i]]=1; else tot[num[i]]++; if(tot[num[i]]+cnt[num[i]][rights]-cnt[num[i]][lefts-1]>maxx||((tot[num[i]]+cnt[num[i]][rights]-cnt[num[i]][lefts-1]==maxx)&&num[i]<anss)) maxx=tot[num[i]]+cnt[num[i]][rights]-cnt[num[i]][lefts-1],anss=num[i]; } for(int i=Right[rights]+1;i<=b;i++) { if(visit[num[i]]!=tim) visit[num[i]]=tim,tot[num[i]]=1; else tot[num[i]]++; if(tot[num[i]]+cnt[num[i]][rights]-cnt[num[i]][lefts-1]>maxx||((tot[num[i]]+cnt[num[i]][rights]-cnt[num[i]][lefts-1]==maxx)&&num[i]<anss)) maxx=tot[num[i]]+cnt[num[i]][rights]-cnt[num[i]][lefts-1],anss=num[i]; } return idx[anss]; } } int main() { //freopen("a.in","r",stdin); n=R(),m=R(); for(int i=1;i<=n;i++) { num[i]=R();temp[i]=num[i]; } pre(); int a,b,t=0; for(int i=1;i<=m;i++) { a=R(),b=R(); a=(a+t-1)%n+1; b=(b+t-1)%n+1; if(a>b) swap(a,b); t=getans(a,b); printf("%d\n",t); } return 0; }

算法復習——分塊算法