http://www.lydsy.com/JudgeOnline/problem.php?id=4865
写题面的人语死早。。。S为空的话也是要把元素插入进去的(要不然岂不是一直为空),然后每次异或的是上一次答案的相反数。。。还有莫名其妙的标点缺失和语句重复。。。
于是就是在问能拆分成最少多少个单调增的序列,显然就是众数个数,所以相当于查询区间众数。
传统做法就是分块,预处理每两块之间的答案,维护前缀和就可以知道对于每个数在块内出现了多少次,然后块外再开个桶,暴力枚举块外的每个数更新答案就行了。时空复杂度都是n*sqrt(n)
由于内存限制只有10M,首先先合理调整块大小,然后考虑答案至少为1,所以凡是在整个序列中只出现过一次的数都可以无视,然后再把其他的数离散化,这样内存消耗就小了一半,可以通过了。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
struct Istream
{
Istream& operator>> (int &x)
{
register char c; x=0;
do c=getchar(); while(c<'0'||c>'9');
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
return *this;
}
}cin;
struct Ostream
{
Ostream& operator<< (int x)
{
int a[12],t=1;
while(x) a[t++]=x%10,x/=10;
while(--t) putchar(a[t]+'0');
return *this;
}
Ostream& operator<< (char c){return putchar(c),*this;}
}cout;
const char endl='\n';
int n,m,size;
int a[60000],b[60000],tot=0;
short mx[150][150];
unsigned short cnt[150][30000];
int ans=0;
int main()
{
cin>>n>>m; size=std::max(sqrt(n),ceil(n/150.0));
for(int i=0;i<n;++i) cin>>a[i],b[i]=a[i];
std::sort(b,b+n);
for(int i=0,j=0;i<n;i=j)
{
for(;j<n&&b[i]==b[j];++j);
if(i+1!=j) b[tot++]=b[i];
}
for(int i=0;i<n;++i)
{
int pos=std::lower_bound(b,b+tot,a[i])-b;
if(pos==tot||b[pos]!=a[i]) a[i]=-1;
else a[i]=pos;
}
int u=(n-1)/size;
for(int i=0;i<=u;++i)
{
memset(b,0,tot<<2);
int kre=-1;
for(int j=i;j<=u;++j)
{
int l=j*size,r=l+size; if(r>n) r=n;
for(;l<r;++l)
if(~a[l])
{
int num=++b[a[l]];
if(kre==-1||num>b[kre]) kre=a[l];
}
mx[i][j]=kre;
}
int l=i*size,r=l+size; if(r>n) r=n;
for(;l<r;++l)
if(~a[l]) ++cnt[i][a[l]];
if(i)
{
for(int j=0;j<tot;++j)
cnt[i][j]+=cnt[i-1][j];
}
}
memset(b,0,sizeof b);
for(int i=1;i<=m;++i)
{
int l,r; cin>>l>>r;
l^=ans,r^=ans; --l,--r;
int x=l/size,y=r/size;
putchar('-');
if(y<=x+1)
{
ans=-1;
for(;l<=r;++l)
if(~a[l])
{
int g=a[l];
int num=(b[g+tot]==i)?(++b[g]):(b[g+tot]=i,b[g]=1);
if(ans==-1||num>b[ans]) ans=g;
}
ans=(~ans)?b[ans]:1;
cout<<ans<<endl;
}
else
{
ans=mx[x+1][y-1];
int ans_c=(ans==-1)?1:cnt[y-1][ans]-cnt[x][ans];
for(int j=(x+1)*size;l<j;++l)
if(~a[l])
{
int g=a[l]; if(ans==g) ++ans_c;
int num=((b[g+tot]==i)?(++b[g]):(b[g+tot]=i,b[g]=1))+(cnt[y-1][g]-cnt[x][g]);
if(ans==-1||num>ans_c) ans=g,ans_c=num;
}
for(int j=y*size;r>=j;--r)
if(~a[r])
{
int g=a[r]; if(ans==g) ++ans_c;
int num=((b[g+tot]==i)?(++b[g]):(b[g+tot]=i,b[g]=1))+(cnt[y-1][g]-cnt[x][g]);
if(ans==-1||num>ans_c) ans=g,ans_c=num;
}
cout<<(ans=ans_c)<<endl;
}
}
return 0;
}