A.异或运算
题意:给出$a[n]$,$b[m]$.一个二维数组$c[i][j]=a[i]\otimes b[j]$。给出$p$个询问。每次询问某个矩形区域内的第$k$大值。
$ n<=1000$ $m<=300000$ $p<=500$
题解:矩形第k大很容易让人想到矩阵乘法这道题,但这是行不通的。因为无法建出整个二维数组,而且询问本身也并不多。
考虑题目的特殊性,这个二维数组是由一个异或确定的。
异或之类的问题从最高位逐位确定的方法一定是对的。
不妨假设当前考虑到第$i$位,那么我们需要知道
满足$x∈[xl,xr]$,$y∈[yl,yr]$,且$(a[x]\otimes b[y]\otimes ans)>>i==1$的二元组$(x,y)$的数量。
感觉$O(1)$是不能做的。然而$n$为什么比起$m$这么小呢?很显然就是让我们暴力呢么
我们把所有的$x$放到$y∈[yl,yr]$所构成的$trie$树中,沿着满足题意的出边走,最后访问一下$size$即可。
区间$trie$?我们可以用可持久化$trie$来搞,$size$只要用前缀和减一下就可以了。
代码:
int n,m,tot,a[maxn],b[maxn],s[maxm],t[maxm][2],rt[maxn];
struct rec{int l,r;}c[maxn];
inline void insert(int now,int z)
{
rt[now]=++tot;int x=rt[now],y=rt[now-1];
s[x]=s[y]+1;
for3(i,30,0)
{
int j=z>>i&1;
t[x][j]=++tot;
t[x][j^1]=t[y][j^1];
x=t[x][j];y=t[y][j];
s[x]=s[y]+1;
}
}
int main()
{
n=read();m=read();
for1(i,n)a[i]=read();
for1(i,m)b[i]=read(),insert(i,b[i]);
int T=read();
while(T--)
{
int xl=read(),xr=read(),yl=read(),yr=read(),k=read(),ans=0,now=0;
for2(i,xl,xr)c[i].l=rt[yl-1],c[i].r=rt[yr];
for3(i,30,0)
{
int tmp=0;
for2(j,xl,xr)
{
int k=a[j]>>i&1,p=1;
tmp+=s[t[c[j].r][k!=p]]-s[t[c[j].l][k!=p]];
}
if(now+tmp>=k)
{
ans^=1<<i;
for2(j,xl,xr)
{
int k=a[j]>>i&1,p=1;
c[j].l=t[c[j].l][k!=p];
c[j].r=t[c[j].r][k!=p];
}
}else
{
now+=tmp;
for2(j,xl,xr)
{
int k=a[j]>>i&1,p=0;
c[j].l=t[c[j].l][k!=p];
c[j].r=t[c[j].r][k!=p];
}
}
}
cout<<ans<<endl;
}
return 0;
}
B.平方运算
题意:维护一个数列$a[n]$,有$m$次操作。每次可以:
1)对所有$i∈[l,r]$,执行$a[i]=a[i]*a[i]\%p$
2)输出$\sum_{i=l}^{r}a[i]$ 不对任何数取模
$ n<=100000$ $m<=100000$
每个测试点内的$p$都一样。$20$个$p$分别如下:
int n,mx=1,p,v[maxn],b[maxn];
struct seg{int sum,mx;}g[4*maxn];
struct rec{int add[62],tag;}t[4*maxn];
inline void pushup(int k)
{
for0(i,mx-1)t[k].add[i]=t[k<<1].add[i]+t[k<<1|1].add[i];
}
inline void update(int k,int x)
{
for0(i,mx-1)b[i]=t[k].add[i];
for0(i,mx-1)t[k].add[i]=b[(i+x)%mx];
(t[k].tag+=x)%=mx;
}
inline void pushdown(int k)
{
if(!t[k].tag)return;
update(k<<1,t[k].tag);update(k<<1|1,t[k].tag);
t[k].tag=0;
}
inline void insert(int k,int l,int r,int x,int y)
{
if(l==r)
{
t[k].tag=0;
t[k].add[0]=y;
for1(i,mx-1)t[k].add[i]=t[k].add[i-1]*t[k].add[i-1]%p;
return;
}
pushdown(k);
if(x<=mid)insert(lch,x,y);else insert(rch,x,y);
pushup(k);
}
inline void pushupp(int k)
{
g[k].sum=g[k<<1].sum+g[k<<1|1].sum;
g[k].mx=max(g[k<<1].mx,g[k<<1|1].mx);
}
inline void change(int k,int l,int r,int x,int y)
{
if(g[k].mx==0)return;
if(l==x&&r==y)
{
if(l==r)
{
g[k].sum=g[k].sum*g[k].sum%p;
g[k].mx--;
if(g[k].mx==0)
{
insert(1,1,n,l,g[k].sum);
g[k].sum=0;
}
return;
}
change(lch,l,mid);change(rch,mid+1,r);
pushupp(k);
return;
}
if(y<=mid)change(lch,x,y);
else if(x>mid)change(rch,x,y);
else change(lch,x,mid),change(rch,mid+1,y);
pushupp(k);
}
inline void add(int k,int l,int r,int x,int y)
{
if(!t[k].add[0])return;
if(l==x&&r==y){update(k,1);return;}
pushdown(k);
if(y<=mid)add(lch,x,y);
else if(x>mid)add(rch,x,y);
else add(lch,x,mid),add(rch,mid+1,y);
pushup(k);
}
inline int query(int k,int l,int r,int x,int y)
{
if(l==x&&r==y)return g[k].sum+t[k].add[0];
pushdown(k);
if(y<=mid)return query(lch,x,y);
else if(x>mid)return query(rch,x,y);
else return query(lch,x,mid)+query(rch,mid+1,y);
}
inline int gcd(int x,int y){return y?gcd(y,x%y):x;}
inline void build(int k,int l,int r)
{
if(l==r)
{
g[k].sum=read();
int t1=g[k].sum,t2=1;
for(;;)
{
if(v[t1]>0){g[k].mx=v[t1];mx=mx*(t2-v[t1])/gcd(mx,t2-v[t1]);break;}
v[t1]=t2;
t2++;
t1=t1*t1%p;
}
t1=g[k].sum;
for0(i,t2)v[t1]=0,t1=t1*t1%p;
return;
}
build(lch);build(rch);
pushupp(k);
}
int main()
{
n=read();int T=read();p=read();
build(1,1,n);
while(T--)
{
int ch=read(),l=read(),r=read();
if(ch)printf("%d\n",query(1,1,n,l,r));
else add(1,1,n,l,r),change(1,1,n,l,r);
}
return 0;
}
感觉这题确实不太好说清楚,有问题可以$q$我$973446154$。
int n,m,a[maxn],b[maxn],c[maxn],d[maxn],ans[maxn];
inline bool cmp(int x,int y)
{
if(a[x]!=a[y])return a[x]<a[y];
else if(b[x]!=b[y])return b[x]<b[y];
else return x<y;
}
int main()
{
n=read();m=read();
for1(i,n+1)a[i]=read(),b[i]=a[i],c[i]=i;
sort(b+1,b+n+2);
sort(c+1,c+n+2,cmp);
for1(i,n+1)d[c[i]]=i;
int now=1;
for3(i,n,1)ans[i]=a[now],now=d[now];
for1(i,n)printf("%d%c",ans[i],i==n?' ':' ');
return 0;
}
评论 (0)