题解——洛谷P2781 传教(线段树)
可以说是数据结构学傻了的典型案例了
昨天跳到这题上
然后思考了一下
噫!好!线段树裸题
然后打完板子,发现\( n \le 10^9 \)
显然线段树直接做不太行
然后这题又只有普及的难度
然后我就打了神奇的动态开点线段树水过
qwq
之后看题解发现正解是\( O(m^2) \)的暴力
因为常数小跑的更快啊qwq
#include <cstdio> #include <algorithm> #include <cstring> #define int long long using namespace std; int cnt=1,tr[150000<<2],tag[150000<<2],lx[150000<<2],rx[150000<<2],n,m,root=1; void pushup(int o){ tr[o]=tr[lx[o]]+tr[rx[o]]; } void pushdown(int o,int ln,int rn){ if(!lx[o]) lx[o]=++cnt; if(!rx[o]) rx[o]=++cnt; if(tag[o]){ tag[lx[o]]+=tag[o]; tag[rx[o]]+=tag[o]; tr[lx[o]]+=tag[o]*ln; tr[rx[o]]+=tag[o]*rn; tag[o]=0; } } void update(int L,int R,int l,int r,int& o,int c){ if(!o) o=++cnt; if(L<=l&&r<=R){ tr[o]+=c*(r-l+1); tag[o]+=c; return; } int mid=(l+r)>>1; pushdown(o,mid-l+1,r-mid); if(L<=mid){ update(L,R,l,mid,lx[o],c); } if(R>mid){ update(L,R,mid+1,r,rx[o],c); } pushup(o); } int query(int L,int R,int l,int r,int &o){ if(!o) o=++cnt; if(L<=l&&r<=R){ return tr[o]; } int ans=0,mid=(l+r)>>1; pushdown(o,mid-l+1,r-mid); if(L<=mid){ ans+=query(L,R,l,mid,lx[o]); } if(R>mid) ans+=query(L,R,mid+1,r,rx[o]); return ans; } void debug(int l,int r,int o){ if(!o) return; printf("o=%d l=%d r=%d tag=%d num=%d lx=%d rx=%d\n",o,l,r,tag[o],tr[o],lx[o],rx[o]); if(l==r) return; int mid=(l+r)>>1; debug(l,mid,lx[o]); debug(mid+1,r,rx[o]); } signed main(){ scanf("%lld %lld",&n,&m); for(int i=1;i<=m;i++){ int opt; scanf("%lld",&opt); if(opt==1){ int l,r,k; scanf("%lld %lld %lld",&l,&r,&k); update(l,r,1,n,root,k); // debug(1,n,root); } else{ int l,r; scanf("%lld %lld",&l,&r); printf("%lld\n",query(l,r,1,n,root) ); } } return 0; }