题意:
一开始给定一个n长序列,元素为1~n。之后又m个询问,共两种:
1)D a b,将[a,b]区间内的元素double,如{1,2,3,4,5}询问D 4 5,则得到{1,2,3,4,4,5,5}
2)Q a b,输出[a,b]区间内重复次数最多的数的个数。
题解:
我们需要维护一个数组cnt[i],表示i的出现次数。那么i的出现位置是[sum[i-1]+1,sum[i]],其中sum[i]表示1到i出现的总次数。
对于D操作,我们找到a位置对应的数字l,b位置对应的数字r。[l,r]区间内的所有cnt[i]都个数翻倍,而对于l和r上的数字则加上相应的个数。b-a<=1e8,,即每次增加个数不会超过10^8,所以总个数不会超过5*10^12。需要用到__int64。
由于n和m很大,所以需要用线段树来维护。
代码:
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <map> #include <set> #include <vector> #include <cctype> using namespace std; #define LL __int64 #define lc (c<<1) #define rc (c<<1|1) const int maxn=5e4+10; struct node{ LL sum,setv,maxv; int l,r; }e[maxn*4]; LL ans,sum_pre,ll,rr; int l,r; void build(int a,int b,int c) { if(a==b) { e[c].l=e[c].r=a; e[c].sum=e[c].maxv=e[c].setv=1; return ; } int mid=(a+b)>>1; build(a,mid,lc); build(mid+1,b,rc); e[c].l=a; e[c].r=b; e[c].sum=e[lc].sum+e[rc].sum; e[c].setv=e[c].maxv=1; } void push_down(int c) { if(e[c].setv!=1) { e[lc].setv*=e[c].setv;e[rc].setv*=e[c].setv; e[lc].sum*=e[c].setv;e[rc].sum*=e[c].setv; e[lc].maxv*=e[c].setv;e[rc].maxv*=e[c].setv; e[c].setv=1; } } void push_up(int c) { e[c].sum=e[lc].sum+e[rc].sum; e[c].maxv=max(e[lc].maxv,e[rc].maxv); } void update1(LL a,int c,int flag)//找到a和b对应的位置l和r { if(e[c].l==e[c].r) { if(flag) { rr=a-sum_pre; r=e[c].l; } else { ll=e[c].sum+sum_pre-a+1; l=e[c].l; } return ; } push_down(c); int mid=(e[c].l+e[c].r)>>1; if(a>sum_pre+e[lc].sum) { sum_pre+=e[lc].sum; update1(a,rc,flag); } else update1(a,lc,flag); } void update2(int a,int b,int c) { if(a>b)return ; if(e[c].l==a&&e[c].r==b) { e[c].setv*=2; e[c].sum*=2; e[c].maxv*=2; return ; } push_down(c); int mid=(e[c].l+e[c].r)>>1; if(b<=mid)update2(a,b,lc); else if(a>mid)update2(a,b,rc); else { update2(a,mid,lc); update2(mid+1,b,rc); } push_up(c); } void update3(int a,int b,int c,LL val) { if(e[c].l==a&&e[c].r==b) { e[c].sum+=val; e[c].maxv+=val; return ; } push_down(c); int mid=(e[c].l+e[c].r)>>1; if(b<=mid)update3(a,b,lc,val); else if(a>mid)update3(a,b,rc,val); push_up(c); } int query2(int a,int b,int c) { if(e[c].l==a&&e[c].r==b) { return e[c].sum; } push_down(c); int mid=(e[c].l+e[c].r)>>1; if(b<=mid)return query2(a,b,lc); else if(a>mid)return query2(a,b,rc); } LL query(int a,int b,int c) { if(e[c].l==a&&e[c].r==b) { return e[c].maxv; } push_down(c); int mid=(e[c].l+e[c].r)>>1; if(b<=mid)return query(a,b,lc); else if(a>mid)return query(a,b,rc); else return max(query(a,mid,lc),query(mid+1,b,rc)); } int main() { int T,tt=0; scanf("%d",&T); while(T--) { int i,j,k,n,m; LL a,b; char s[2]; scanf("%d%d",&n,&m); build(1,n,1); printf("Case #%d:\n",++tt); for(i=0;i<m;i++) { scanf("%s%I64d%I64d",s,&a,&b); if(s[0]=='D') { sum_pre=0; update1(a,1,0); sum_pre=0; update1(b,1,1); if(l==r)update3(l,r,1,b-a+1); else { update3(l,l,1,ll); update3(r,r,1,rr); } update2(l+1,r-1,1); } else { ans=0; sum_pre=0; update1(a,1,0); sum_pre=0; update1(b,1,1); //printf("*%d %d %I64d %I64d %I64d\n",l,r,ll,rr,b-a+1); if(l==r)ans=max(ans,b-a+1); else { ans=max(ans,ll); ans=max(ans,rr); } if(l+1<=r-1)ans=max(ans,query(l+1,r-1,1)); printf("%I64d\n",ans); } } //for(i=1;i<=n;i++)printf("%d\n",query2(i,i,1)); } return 0; } /* 1 5 5 D 1 5 D 5 7 Q 8 10 D 1 9 Q 1 15 */