huangzirui @ 2019-11-08 23:33:27
QAQ 85分T3点。(然后这三个点都是2.1几秒呜呜呜)
(复杂度上限在query
里面)
#include <bits/stdc++.h>
#define ll long long
#define RE register
using namespace std;
int i,j,k,n,m;
void read(int &x){
char c;x=0;int b=1;do{c=getchar();if(c==45)b=-1;}while(c>57||c<48);
do x=x*10+c-48,c=getchar();while(c<=57&&c>=48);x*=b;
}
void read(ll &x){
char c;x=0;int b=1;do{c=getchar();if(c==45)b=-1;}while(c>57||c<48);
do x=x*10+c-48,c=getchar();while(c<=57&&c>=48);x*=b;
}
const int maxn=40000+10,maxN=200+10;
int N,a[maxn];
int mp[maxn],len=1;
void make(int &x){
int L=1,R=len;
while(R>=L){
int Mid=L+R>>1;
if(mp[Mid]==x){x=Mid;return;}
if(mp[Mid]>x)R=Mid-1;
else L=Mid+1;
}
}
void in(){
read(n);read(m);
N=sqrt(n);
for(int i=1;i<=n;i++)
read(a[i]),mp[i]=a[i];
sort(mp+1,mp+1+n);
for(int i=2;i<=n;i++)
if(mp[i]!=mp[i-1])
mp[++len]=mp[i];
for(int i=1;i<=n;i++)
make(a[i]);
}
int Sum[maxN][maxN];
int B[maxn];
int block[maxn],Start[maxN],End[maxN];
void init_block(){
for(int i=1;i<=n;i++){
block[i]=(i-1)/N+1;
if(block[i]!=block[i-1])
Start[block[i]]=i;
End[block[i]]=i;
}
}
void init_Sum(){
for(int i=1;i<=N;i++){
memset(B,0,sizeof(B));
int now=i,Max1=0,Max2=0;
for(int j=Start[i];j<=n;j++){
B[a[j]]++;
if(B[a[j]]>Max1 || (B[a[j]]==Max1 && Max2>a[j])){
Max1=B[a[j]];
Max2=a[j];
}
if(j==End[now]){
Sum[i][now]=Max2;
++now;
}
}
}
}
int Num[maxn][maxN];
void init_Num(){
int now=1;
for(int i=1;i<=n;i++){
B[a[i]]++;
if(End[now]==i){
for(int j=1;j<=n;j++)
Num[j][now]=B[j];
++now;
}
}
}
void init(){
init_block();
init_Sum();
init_Num();
}
int Q[4*maxN];
int find(int l,int r,int x){
//cout<<"find:"<<l<<' '<<r<<' '<<x<<endl;
int ans=0;
if(block[l]==block[r]){
for(int i=l;i<=r;i++)
if(a[i]==x)
++ans;
}else{
for(int i=l;block[i]==block[l];i++)
if(a[i]==x)
++ans;
for(int i=r;block[i]==block[r];i--)
if(a[i]==x)
++ans;
//cout<<"FIND:"<<block[r]-1<<' '<<block[l]<<' '<<x<<' '<<Num[x][block[r]-1]<<endl;
ans+=Num[x][block[r]-1]-Num[x][block[l]];
}
return ans;
}
int query(int l,int r){
RE int len=0,i;
if(block[l]==block[r]){
for(i=l;i<=r;i++)
Q[++len]=a[i];
}else{
for(i=l;block[i]==block[l];i++)
Q[++len]=a[i];
//cout<<"len:"<<len<<' ';
for(i=r;block[i]==block[r];i--)
Q[++len]=a[i];
//cout<<len<<' ';
if(block[r]-block[l]>1)
Q[++len]=Sum[block[l]+1][block[r]-1];
//cout<<len<<' ';
}
sort(Q+1,Q+1+len);
//cout<<"len:"<<len<<' ';
RE int L=1;
for(i=2;i<=len;i++)
if(Q[i]!=Q[i-1])
Q[++L]=Q[i];
len=L;
//cout<<len<<endl;
//cout<<l<<' '<<block[l]<<' '<<r<<' '<<block[r]<<endl;
int Max1=0,Max2=0;
for(i=1;i<=len;i++){
int now=find(l,r,Q[i]);
//cout<<i<<' '<<Q[i]<<' '<<now<<endl;
if(now>Max1 || (Max1==now && Max2>Q[i])){
Max1=now;
Max2=Q[i];
}
}
int ans=mp[Max2];
printf("%d\n",ans);
return ans;
}
void Query(){
RE int lastans=0,l,r;
for(int i=1;i<=m;i++){
read(l);read(r);
l=l+lastans-1;
r=r+lastans-1;
if(l>=n)l-=n;
if(r>=n)r-=n;
++l;++r;
if(l>r)swap(l,r);
lastans=query(l,r)%n;
//cout<<l<<' '<<r<<endl;
}
}
int main() {
in();
init();
Query();
//cerr << 1.0*clock()/CLOCKS_PER_SEC << endl;
return 0;
}
by Absurdity @ 2019-11-08 23:34:41
秒切黑题,%
by huangzirui @ 2019-11-08 23:36:38
%%% @Mysterious_wind
by Absurdity @ 2019-11-08 23:38:59
@huangzirui 是平衡树吗?
by Absurdity @ 2019-11-08 23:39:54
看不懂奇特的码风
by Absurdity @ 2019-11-08 23:40:38
还是分块啊
by Absurdity @ 2019-11-08 23:41:16
我还是太菜了啊
by huangzirui @ 2019-11-08 23:44:16
@Mysterious_wind 您tql
by wh_ZH @ 2019-11-08 23:46:20
建议学习
这份代码常数挺大的。。。也许调调块大小能过?
by 失之_连心 @ 2019-11-09 08:05:58
巨佬Orz @huangzirui
by huangzirui @ 2019-11-09 08:11:37
@wh_ZH QAQ我写的就是根号算法啊
然后自带大常数实在卡不动了。。