题意:N个格子排出一排,开始格子颜色都是1;现在有M个操作:
或,把区间[L,R]颜色改为c;
或,查询一共有多少格子颜色为c。
最后求颜色最多的数量。
数据是随机的,且强制在线。
思路:ODT裸题。维护相同颜色的区间。 split拆分区间,assign操作收缩区间,由于数据随机,区间的个数趋近于log级别。
注意split的时候先split(R+1),再split(L);因为这个我wa20了;在这里有写。 大概就是会改变指针啥的,我对iterator不了解,所以不知道,记下来好了。
这个在大量区间操作的题目中,如果说明了随机的,或者想试一试的情况下,还是非常优秀(暴力)的。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; struct in{ int L,R,v; in(){} in(int LL,int RR,int vv):L(LL),R(RR),v(vv){} friend bool operator<(in a,in b){ if(a.L==b.L) return a.R<b.R; return a.L<b.L; } }; set<in>s; #define IT set<in>::iterator int num[100010],ans; IT split(int pos) { IT it=s.lower_bound(in(pos,-2,-2)); if(it!=s.end()&&(*it).L==pos) return it; it--; int l=(*it).L,r=(*it).R,v=(*it).v; s.erase(it); s.insert(in(l,pos-1,v)); return s.insert(in(pos,r,v)).first; } void Assign(int L,int R,int X) { IT it2=split(R+1),it1=split(L); for(IT it=it1;it!=it2;it++) { num[(*it).v]-=((*it).R-(*it).L+1); } s.erase(it1,it2); s.insert(in(L,R,X)); num[X]+=R-L+1; } int main() { int N,L,C,P,X,A,B,S; scanf("%d%d%d",&L,&C,&N); s.insert(in(0,L-1,1)); num[1]=L; rep(i,1,N){ scanf("%d%d%d%d",&P,&X,&A,&B); A%=L; B%=L; S=num[P]%L; int l=(A+1LL*S*S%L)%L,r=(A+1LL*(S+B)*(S+B)%L)%L; Assign(min(l,r),max(l,r),X); } rep(i,1,C) ans=max(ans,num[i]); printf("%d\n",ans); return 0; }