hdu 6162 離線樹鏈剖分
阿新 • • 發佈:2018-12-01
題意:一個樹,點權,查詢x到y路徑上 價值在[a,b]之間的點的權值和
思路:剖分模板題,首先要想到離線處理,第一步將查詢分為query(x,y,0,b)-query(x,y,0,a);接下來我們就發現了可以按照點權的大小以及查詢a的大小離線處理,這樣就相當於只查詢query(x,y)。。。故直接上個剖分點權的模板
程式碼:
#include<bits/stdc++.h> using namespace std; #define ls (rt<<1) #define rs (rt<<1|1) #define mid (tr[rt].l+(tr[rt].r-tr[rt].l)/2) #define X first #define Y second #define PB push_back #define MP make_pair #define MEM(x,y) memset(x,y,sizeof(x)); #define bug(x) cout<<"bug"<<x<<endl; typedef long long ll; const int maxn =1e5+100; #pragma comment(linker, "/STACK:1024000000,1024000000") typedef pair<int,pair<int,int> > pii; struct TREE{ll sum,l,r,tag;}tr[maxn*4]; int pos[maxn],sz[maxn],top[maxn],son[maxn], fa[maxn],id[maxn],deep[maxn],cnt=0; vector<int> g[maxn]; //void pushup(int rt){tr[rt].sum=tr[ls].sum+tr[rs].sum;} void build(int l,int r,int rt){ tr[rt].l=l,tr[rt].r=r; if(l==r){tr[rt].sum=0;return ;} int midd=l+(r-l)/2; build(l,midd,ls),build(midd+1,r,rs); tr[rt].sum=tr[ls].sum+tr[rs].sum; } void pushdown(int rt){ if(tr[rt].tag){ tr[ls].tag=(tr[ls].tag+tr[rt].tag); tr[rs].tag=(tr[rs].tag+tr[rt].tag); tr[ls].sum=(tr[ls].sum+(tr[ls].r-tr[ls].l+1)*tr[rt].tag); tr[rs].sum=(tr[rs].sum+(tr[rs].r-tr[rs].l+1)*tr[rt].tag); tr[rt].tag=0; } } void update(int l,int r,int c,int rt){ if(l<=tr[rt].l&&tr[rt].r<=r){ tr[rt].sum=(tr[rt].sum+(c*(tr[rt].r-tr[rt].l+1))); tr[rt].tag+=c; return ; } pushdown(rt); if(l<=mid) update(l,r,c,ls); if(r>mid) update(l,r,c,rs); tr[rt].sum=tr[ls].sum+tr[rs].sum; } ll query(int l,int r,int rt){ if(l<=tr[rt].l&&tr[rt].r<=r) return tr[rt].sum; pushdown(rt); ll ans=0; if(l<=mid) ans+=query(l,r,ls); if(r>mid) ans+=query(l,r,rs); return ans; } void dfs1(int x,int fat,int dep){ deep[x]=dep,fa[x]=fat,sz[x]=1; for(int i=0;i<g[x].size();i++){ int v=g[x][i]; if(v!=fat){ dfs1(v,x,dep+1); sz[x]+=sz[v]; if(son[x]==-1||sz[son[x]]<sz[v]) son[x]=v; } } } void dfs2(int x,int tp){ top[x]=tp;pos[x]=++cnt;id[pos[x]]=x; if(son[x]==-1) return ; dfs2(son[x],tp); for(int i=0;i<g[x].size();i++){ int v=g[x][i]; if(v!=fa[x]&&v!=son[x]) dfs2(v,v); } } ll add(int t1,int t2,int c,int ok){ ll u=t1,v=t2,ans=0; //bug("F") while(top[u]!=top[v]){ if(deep[top[u]]>deep[top[v]]) swap(u,v); if(!ok)update(pos[top[v]],pos[v],c,1); else ans+=query(pos[top[v]],pos[v],1); v=fa[top[v]]; } if(deep[u]>deep[v]) swap(u,v);//!! if(!ok) update(pos[u],pos[v],c,1); else ans+=query(pos[u],pos[v],1); return ans; } int a[maxn]; pii Q[maxn*3]; int ql[maxn],qr[maxn],qll[maxn],qrr[maxn]; ll ans[maxn]; int main(){ int n,P,v,u; while(scanf("%d%d",&n,&P)!=EOF){ memset(son,-1,sizeof(son)); MEM(ans,0); for(int i=0;i<=n+5;i++) g[i].clear(); int x,y,num=0; cnt=0; for(int i = 1; i <= n; i++){ scanf("%d",&a[i]); Q[num++]=MP(a[i],MP(0,i)); } for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs1(1,-1,1); dfs2(1,1); build(1,n,1); for(int i = 1; i <=P; i++){ scanf("%d%d%d%d",&ql[i],&qr[i],&qll[i],&qrr[i]); Q[num++]=MP(qll[i],MP(-1,i)); Q[num++]=MP(qrr[i],MP(1,i)); } sort(Q,Q+num); //bug(1) for(int i=0;i<num;i++){ int ii=Q[i].Y.Y; if(Q[i].Y.X==0)add(ii,ii,Q[i].X,0); else if(Q[i].Y.X==-1)ans[ii]-=add(ql[ii],qr[ii],0,1); else ans[ii]+=add(ql[ii],qr[ii],0,1); } for(int i = 1; i <=P; i++) printf("%lld%c",ans[i]," \n"[i==P]); } return 0; }