洛谷.3374.[模板]樹狀數組1(CDQ分治)
阿新 • • 發佈:2018-03-15
%d com 鏈接 .html mod include 教程 UC 可能
題目鏈接
簡易CDQ分治教程
//每個操作分解為一個有序數對(t,p),即(時間,操作位置),時間默認有序,用CDQ分治對位置排序(可能說法不對 不要太在意 歡迎指出)
#include <cstdio>
#include <cctype>
#define gc() getchar()
//typedef long long LL;
const int N=5e5+5;
int n,m,Ans[N];
struct Ques
{
int id,pos,val;//id:0:Modify 1:left point 2:right point
Ques() {;}
Ques(int i,int p,int v): id(i),pos(p),val(v) {};
// Ques(int i=0,int p=0,int v=0) {id=i,pos=p,val=v;}
bool operator <(const Ques &a) const{
return pos==a.pos?id<a.id:pos<a.pos;
}
}q[N*3],tmp[N*3];
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if (c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
void CDQ(int l,int r)
{
if(l<r)
{
int m=l+r>>1; CDQ(l,m), CDQ(m+1,r);
int p1=l,p2=m+1,t=0,sum=0;
while(p1<=m&&p2<=r)
{//註意理解歸並的內涵: 對於同被劃分到左/右邊的,它們之間的影響已在合並該大區間前計算了,所以當前是不需要管的
if(q[p1]<q[p2])
{//對於左邊的區間統計修改值(左邊表示操作位置靠左 所以會對右邊的詢問產生影響)
if(!q[p1].id) sum+=q[p1].val;
tmp[t++]=q[p1++];
}
else
{//對於右邊的區間更新查詢
if(q[p2].id==1) Ans[q[p2].val]-=sum;
else if(q[p2].id==2) Ans[q[p2].val]+=sum;
tmp[t++]=q[p2++];
}
}
while(p1<=m) tmp[t++]=q[p1++];//無查詢了
while(p2<=r)
{
if(q[p2].id==1) Ans[q[p2].val]-=sum;
else if(q[p2].id==2) Ans[q[p2].val]+=sum;
tmp[t++]=q[p2++];
}
for(int i=0; i<t; ++i) q[l+i]=tmp[i];
}
}
int main()
{
n=read(),m=read();
int qcnt=0,acnt=0;
for(int i=1; i<=n; ++i) q[++qcnt]=Ques(0,i,read());
for(int id,l,r,i=1; i<=m; ++i)
{
id=read(),l=read(),r=read();
if(id==1) q[++qcnt]=Ques(0,l,r);
else ++acnt, q[++qcnt]=Ques(1,l-1,acnt), q[++qcnt]=Ques(2,r,acnt);
}
CDQ(1,qcnt);
for(int i=1; i<=acnt; ++i) printf("%d\n",Ans[i]);
return 0;
}
洛谷.3374.[模板]樹狀數組1(CDQ分治)