牛客 Rabbit的数列 (线段树维护值为x的个数+区间覆盖)
https://ac.nowcoder.com/acm/contest/907/C
链接:https://ac.nowcoder.com/acm/contest/907/C
来源:牛客网
题目描述
Rabbit得到了一个长度为N的数列(数列编号从0到N−1)。数列中每个数vali满足1<=vali<=C。
初始时数列中每个数均为1,现在Rabbit要对这个数列进行Q次操作,每次操作给出四个数:X Y A B,首先查询数列中值为X的个数P,然后计算出L,R:
L=(A+(P+B)2)mod N
R=(A+(P∗B)2)mod N
并将范围[min(L,R),max(L,R)]内的所有数改为Y。
最后询问经过Q次操作后数列中出现次数最多的那个数出现了几次。
初始时数列中每个数均为1,现在Rabbit要对这个数列进行Q次操作,每次操作给出四个数:X Y A B,首先查询数列中值为X的个数P,然后计算出L,R:
L=(A+(P+B)2)mod N
R=(A+(P∗B)2)mod N
并将范围[min(L,R),max(L,R)]内的所有数改为Y。
最后询问经过Q次操作后数列中出现次数最多的那个数出现了几次。
输入描述:
第一行三个整数N,C,Q。
接下来Q行,每行四个整数X,Y,A,B,表示一个操作。
输出描述:
输出一个整数,表示经过Q次操作后数列中出现次数最多的那个数出现的次数。
示例1
输出
复制2
分析:我们可以维护一个区间最大最小值,这样就可以在log的时间内知道值为x 的个数有多少的 。因为mn[x]=mx[x] 表示这个区间都为Y,故无需在向下查找
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; typedef long long ll; int vis[maxn]; int lazy[maxn*4],mx[maxn*4],mn[maxn*4]; void pushdown(int id,int l,int r) { if(lazy[id]) { mx[id]=mn[id]=lazy[id]; if(l!=r) { lazy[id<<1|1]=lazy[id<<1]=lazy[id]; mx[id<<1]=mx[id<<1|1]=lazy[id]; mn[id<<1]=mn[id<<1|1]=lazy[id]; } lazy[id]=0; } } void update(int id,int l,int r,int ql,int qr,int v) { pushdown(id,l,r); if(ql<=l&&r<=qr&&mx[id]==mn[id]) { vis[mx[id]]-=(r-l+1); vis[v]+=(r-l+1); lazy[id]=v; pushdown(id,l,r); return ; } int mid=(l+r)>>1; if(ql<=mid) update(id<<1,l,mid,ql,qr,v); if(qr>mid) update(id<<1|1,mid+1,r,ql,qr,v); mx[id]=max(mx[id<<1],mx[id<<1|1]); mn[id]=min(mn[id<<1],mn[id<<1|1]); } int main() { int n,c,q,x,y; ll a,b; scanf("%d%d%d",&n,&c,&q); // memset(mn,1,sizeof(mn)); // memset(mx,1,sizeof(mx)); vis[1]=n; lazy[1]=1; while(q--) { scanf("%d%d%lld%lld",&x,&y,&a,&b); int p=vis[x]; int l=(a+(p+b)%n*(p+b)%n)%n+1; int r=(a+p*b%n*p%n*b%n)%n+1; if(l>r) swap(l,r); update(1,1,n,l,r,y); } int ans=0; for(int i=1;i<=c;i++) ans=max(ans,vis[i]); printf("%d\n",ans); }