http://acm.hdu.edu.cn/showproblem.php?pid=3971
又学到了新姿势 居然还能每隔一段时间排个序...
通过维护区间最大最小值来剪枝 但肯定不够
如果一个数列是有序的 那这样维护区间最值 就相当于维护区间端点了 从而有logn得复杂度 所以可以每隔一定循环次数就把数列排序重新建树
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 0x3f3f3f3f3f3f3f3f
struct node
{
ll minn;
ll maxx;
ll laz;
};
node tree[1000010];
ll num[250010];
int n,q;
void pushup(int cur)
{
tree[cur].minn=min(tree[2*cur].minn,tree[2*cur+1].minn);
tree[cur].maxx=max(tree[2*cur].maxx,tree[2*cur+1].maxx);
}
void pushdown(int cur)
{
if(tree[cur].laz!=0)
{
tree[2*cur].minn+=tree[cur].laz;
tree[2*cur].maxx+=tree[cur].laz;
tree[2*cur].laz+=tree[cur].laz;
tree[2*cur+1].minn+=tree[cur].laz;
tree[2*cur+1].maxx+=tree[cur].laz;
tree[2*cur+1].laz+=tree[cur].laz;
tree[cur].laz=0;
}
}
void build(int l,int r,int cur)
{
int m;
tree[cur].laz=0;
if(l==r)
{
tree[cur].maxx=tree[cur].minn=num[l];
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(cur);
}
void update(ll pl,ll pr,ll val,int cur)
{
if(pl<=tree[cur].minn&&tree[cur].maxx<=pr)
{
tree[cur].minn+=val;
tree[cur].maxx+=val;
tree[cur].laz+=val;
return;
}
pushdown(cur);
if(!(tree[2*cur].maxx<pl||tree[2*cur].minn>pr)) update(pl,pr,val,2*cur);
if(!(tree[2*cur+1].maxx<pl||tree[2*cur+1].minn>pr)) update(pl,pr,val,2*cur+1);
pushup(cur);
}
int query(ll pl,ll pr,int l,int r,int cur)
{
int res,m;
if(pl<=tree[cur].minn&&tree[cur].maxx<=pr)
{
return r-l+1;
}
pushdown(cur);
res=0,m=(l+r)/2;
if(!(tree[2*cur].maxx<pl||tree[2*cur].minn>pr)) res+=query(pl,pr,l,m,2*cur);
if(!(tree[2*cur+1].maxx<pl||tree[2*cur+1].minn>pr)) res+=query(pl,pr,m+1,r,2*cur+1);
return res;
}
void reset(int l,int r,int cur)
{
int m;
if(l==r)
{
num[l]=tree[cur].minn;
return;
}
pushdown(cur);
m=(l+r)/2;
reset(l,m,2*cur);
reset(m+1,r,2*cur+1);
}
int main()
{
ll l,r,d;
int i,j;
char op[10];
while(scanf("%d%d",&n,&q)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%lld",&num[i]);
}
sort(num+1,num+n+1);
build(1,n,1);
for(i=1;i<=q;i++)
{
scanf("%s",op);
if(op[0]=='C')
{
scanf("%lld%lld%lld",&l,&r,&d);
update(l,r,d,1);
}
else
{
scanf("%lld%lld",&l,&r);
printf("%d\n",query(l,r,1,n,1));
}
if(i%4000==0)
{
reset(1,n,1);
sort(num+1,num+n+1);
build(1,n,1);
}
}
}
return 0;
}