第一次写cdq分治。
感觉这个题就是按时间递归分治,然后通过每次计算左区间内(时间早)操作对右区间(时间晚)中的查询结果的影响。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
struct node
{
int inde;
int val;
int type;
operator < (const node &a)const
{
return a.inde==inde?type<a.type:inde<a.inde;
}
}op[maxn], tmp[maxn];
int ans[maxn];
void cdq(int l, int r)
{
if(r-l<=1)return;
// printf("%d %d\n", l, r);
int mid=(r+l)>>1;
cdq(l, mid);
cdq(mid, r);
int sum=0, o=0, q=l, p=mid;
while(q<mid && p<r)
{
if(op[q]<op[p])
{
if(op[q].type==1 || op[q].type==2)
{
sum+=op[q].val;
}
tmp[o++]=op[q++];
}
else
{
if(op[p].type==3)
{
ans[op[p].val]-=sum;
}
else if(op[p].type==4)
{
// printf("%d\n", op[p].val);
ans[op[p].val]+=sum;
}
tmp[o++]=op[p++];
}
}
while(q<mid)
{
tmp[o++]=op[q++];
}
while(p<r)
{
if(op[p].type==3)
{
ans[op[p].val]-=sum;
}
else if(op[p].type==4)
{
// printf("%d\n", op[p].val);
ans[op[p].val]+=sum;
}
tmp[o++]=op[p++];
}
for(int i=0; i<o; i++)op[i+l]=tmp[i];
return;
}
int main()
{
int e=1, t;
cin>>t;
int n, i, j, qid=0, l, r;
char str[11];
while(t--)
{
memset(ans, 0, sizeof ans);
qid=0;
int aid=0;
scanf("%d", &n);
for(i=1; i<=n; i++)
{
scanf("%d", &op[qid].val);
op[qid].type=1;
op[qid].inde=i;
qid++;
}
while(~scanf("%s", str))
{
if(str[0]=='E')
{
break;
}
if(str[0]=='Q')
{
scanf("%d%d", &l, &r);
op[qid].inde=l-1;
op[qid].val=aid;
op[qid].type=3;
qid++;
op[qid].inde=r;
op[qid].val=aid++;
op[qid].type=4;
qid++;
}
else if(str[0]=='A')
{
scanf("%d%d", &l, &r);
op[qid].inde=l;
op[qid].val=r;
op[qid].type=1;
qid++;
}
else
{
scanf("%d%d", &l, &r);
op[qid].inde=l;
op[qid].val=-1*r;
op[qid].type=2;
qid++;
}
}
cdq(0, qid);
printf("Case %d:\n", e++);
for(i=0; i<aid; i++)
{
printf("%d\n", ans[i]);
}
}
return 0;
}