线段树
点值存 每个种类的个数,
维护 :区间和sum,区间最大值max,
操作:区间乘2,点加值
查询:区间和,区间最大值
懒标记:lazy区间乘数(标记的是当前区间子区间的lazy,当前区间已经更新完成了)
pushup,pushdown
http://blog.youkuaiyun.com/xcszbdnl/article/details/38736915
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
#define ll __int64
#define EP 1e-10
#define N 50050
struct node
{
int l,r;
ll sum,max,lazy;
}tree[4*N];
void pushup(int id)
{
tree[id].max=max(tree[id<<1].max,tree[id<<1|1].max);
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}
void pushdown(int id)
{
if(tree[id].lazy>1)
{
tree[id<<1].sum*=tree[id].lazy;
tree[id<<1|1].sum*=tree[id].lazy;
tree[id<<1].max*=tree[id].lazy;
tree[id<<1|1].max*=tree[id].lazy;
tree[id<<1].lazy*=tree[id].lazy;
tree[id<<1|1].lazy*=tree[id].lazy;
tree[id].lazy=1;
}
}
void build(int id,int x,int y)
{
tree[id].l=x;
tree[id].r=y;
tree[id].lazy=1;
if(x==y)
{
tree[id].sum=tree[id].max=1;
return ;
}
int mid=(x+y)>>1;
build(id<<1,x,mid);
build(id<<1|1,mid+1,y);
pushup(id);
}
void add(int id,int x,ll y)
{
if(tree[id].l==tree[id].r && tree[id].l==x)
{
tree[id].sum+=y;
tree[id].max+=y;
return ;
}
pushdown(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(x<=mid)
add(id<<1,x,y);
else
add(id<<1|1,x,y);
pushup(id);
}
ll querysum(int id,int x,int y)
{
if(tree[id].l==x && tree[id].r==y)
{
return tree[id].sum;
}
pushdown(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(y<=mid)
return querysum(id<<1,x,y);
else if(mid+1<=x)
return querysum(id<<1|1,x,y);
else return querysum(id<<1,x,mid)+querysum(id<<1|1,mid+1,y);
}
void cheng(int id,int x,int y)
{
if(tree[id].l==x && tree[id].r==y)
{
tree[id].sum*=2;
tree[id].max*=2;
tree[id].lazy*=2;
return ;
}
pushdown(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(y<=mid)
cheng(id<<1,x,y);
else if(mid+1<=x)
cheng(id<<1|1,x,y);
else {
cheng(id<<1,x,mid);
cheng(id<<1|1,mid+1,y);
}
pushup(id);
}
ll querymax(int id,int x,int y)
{
if(tree[id].l==x && tree[id].r==y)
return tree[id].max;
pushdown(id);
int mid=(tree[id].l+tree[id].r)>>1;
if(y<=mid)
return querymax(id<<1,x,y);
else if(mid+1<=x)
return querymax(id<<1|1,x,y);
else
return max(querymax(id<<1,x,mid),querymax(id<<1|1,mid+1,y));
}
int find(int id,ll x)
{
if(tree[id].l==tree[id].r)
return tree[id].l;
pushdown(id);
if(x>tree[id<<1].sum)
return find(id<<1|1,x-tree[id<<1].sum);
else
return find(id<<1,x);
}
int main()
{
int t,n,m,i,j,k;
int res=0;
scanf("%d",&t);
while(t--)
{
res++;
scanf("%d%d",&n,&m);
build(1,1,n);
char op;
ll a,b;
printf("Case #%d:\n",res);
while(m--)
{
scanf(" %c%I64d%I64d",&op,&a,&b);
int l=find(1,a);
int r=find(1,b);
if(op=='D')
{
if(l==r)
{
add(1,l,b-a+1);
}
else
{
ll t1=querysum(1,1,l);
ll t2=querysum(1,1,r-1);
add(1,l,t1-a+1);
add(1,r,b-t2);
if(l+1<=r-1)
cheng(1,l+1,r-1);
}
}
else if(op=='Q')
{
ll mx;
if(l==r)
mx=b-a+1;
else
{
ll t1=querysum(1,1,l);
ll t2=querysum(1,1,r-1);
mx=max(t1-a+1,b-t2);
if(l+1<=r-1)
mx=max(mx,querymax(1,l+1,r-1));
}
printf("%I64d\n",mx);
}
}
}
}