题目链接:https://www.luogu.org/problemnew/show/P3178
题目大意:三种操作,按题目意思操作即可。
思路:树链剖分板子。单点修改,区间修改,区间查询。
ACCode:
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define ll long long #define Pair pair //#define max(a,b) (a)>(b)?(a):(b) //#define min(a,b) (a)<(b)?(a):(b) #define clean(a,b) memset(a,b,sizeof(a))// ?? //std::ios::sync_with_stdio(false); // register const int MAXN=1e5+10; const int INF32=0x3f3f3f3f; const ll INF64=0x3f3f3f3f3f3f3f3f; const ll mod=1e9+7; const double PI=acos(-1.0); const double EPS=1.0e-8; class Segment{ ll TreeSum[MAXN<<2],TreeMAX[MAXN<<2],Lazy[MAXN<<2],Size[MAXN<<2]; void PushDown(int rt){ if(Lazy[rt]==0) return ; TreeSum[rt<<1]=(TreeSum[rt<<1]+Size[rt<<1]*Lazy[rt]); TreeSum[rt<<1|1]=(TreeSum[rt<<1|1]+Size[rt<<1|1]*Lazy[rt]); Lazy[rt<<1]=(Lazy[rt<<1]+Lazy[rt]); Lazy[rt<<1|1]=(Lazy[rt<<1|1]+Lazy[rt]); Lazy[rt]=0; } public : void Intt(){ clean(Lazy,0);clean(Size,0); } public : void Build(int l,int r,int rt,int a[]){ Size[rt]=r-l+1; // printf("rt=%d l=%d r=%d Tree[rt]=%d\n",rt,l,r,Tree[rt]); if(l==r){ TreeSum[rt]=1ll*a[l];//TreeMAX[rt]=a[l]; return ; }int mid=(l+r)>>1; Build(l,mid,rt<<1,a);Build(mid+1,r,rt<<1|1,a); TreeSum[rt]=(TreeSum[rt<<1]+TreeSum[rt<<1|1]); // TreeMAX[rt]=max(TreeMAX[rt<<1],TreeMAX[rt<<1|1]); } public : void Update(int ql,int qr,int val,int l,int r,int rt){ if(ql<=l&&r<=qr){ TreeSum[rt]+=1ll*Size[rt]*val;//TreeMAX[rt]=val; Lazy[rt]+=val; return ; }int mid=(l+r)>>1; PushDown(rt); if(ql<=mid) Update(ql,qr,val,l,mid,rt<<1); if(qr>mid) Update(ql,qr,val,mid+1,r,rt<<1|1); TreeSum[rt]=(TreeSum[rt<<1]+TreeSum[rt<<1|1]); // TreeMAX[rt]=max(TreeMAX[rt<<1],TreeMAX[rt<<1|1]); } public : ll QuerySum(int ql,int qr,int l,int r,int rt){ if(ql<=l&&r<=qr) return TreeSum[rt]; PushDown(rt); int mid=(l+r)>>1; ll ans=0; if(ql<=mid) ans=(ans+QuerySum(ql,qr,l,mid,rt<<1)); if(qr>mid) ans=(ans+QuerySum(ql,qr,mid+1,r,rt<<1|1)); return ans; } public : int QueryMAX(int ql,int qr,int l,int r,int rt){ if(ql<=l&&r<=qr) return TreeMAX[rt]; int mid=(l+r)>>1; int ans=-INF32; if(ql<=mid) ans=max(ans,QueryMAX(ql,qr,l,mid,rt<<1)); if(qr>mid) ans=max(ans,QueryMAX(ql,qr,mid+1,r,rt<<1|1)); return ans; } public : void Show(int l,int r,int rt){ printf("rt=%d l=%d r=%d TreeMAX[rt]=%d TreeSum[rt]=%d\n",rt,l,r,TreeMAX[rt],TreeSum[rt]); if(l==r) return ; int mid=(l+r)>>1; Show(l,mid,rt<<1);Show(mid+1,r,rt<<1|1); } }; struct Node1{ int v,val,nxt; Node1(int _v=0,int _val=0,int _nxt=0){ v=_v;val=_val;nxt=_nxt; } }; Segment Seg; Node1 Edge[MAXN<<2]; int Head[MAXN],Ecnt; int Deep[MAXN],Fa[MAXN],Size[MAXN],Son[MAXN]; int Idx[MAXN],Icnt;//重新标号 int Top[MAXN]; int A[MAXN],B[MAXN]; int n,m; void Intt(){ Seg.Intt(); clean(Head,-1);Ecnt=0; clean(Deep,0);clean(Fa,-1);clean(Size,0);clean(Son,-1); Icnt=0; } void AddEdge(int u,int v,int val){ Edge[Ecnt]=Node1(v,val,Head[u]); Head[u]=Ecnt++; } int DFS1(int u,int fa,int dep){ Deep[u]=dep; Fa[u]=fa; Size[u]=1; int maxson=-1; for(int i=Head[u];i+1;i=Edge[i].nxt){ int temp=Edge[i].v; if(temp==fa) continue; Size[u]+=DFS1(temp,u,dep+1); if(Size[temp]>maxson){ maxson=Size[temp]; Son[u]=temp; } }return Size[u]; } void DFS2(int u,int topfa){ Idx[u]=++Icnt; // cout<<"u,Idx[u]"<Deep[r]) swap(l,r); ans+=Seg.QuerySum(Idx[l],Idx[r],1,n,1); return ans; } int main(){ scanf("%d%d",&n,&m);Intt(); for(int i=1;i<=n;++i){ scanf("%d",&A[i]); } for(int i=1;i