题意:
一开始给定一个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
*/