1. 程式人生 > >BZOJ4154——IPSC2015 Generating Synergy

BZOJ4154——IPSC2015 Generating Synergy

題意:AC通道
題解:
這題有個十分巧妙的解法。
因為有子樹修改,而又不是整棵子樹的修改,直接上dfs序是不行的。
考慮它每次修改的只有子節點,而且有距離限制,我們想到這是與點的深度有關的問題。
於是我們把樹上的點抽象到二維平面上,橫座標為其dfs序,縱座標為其深度,這樣每次的修改就對應一個區域的染色操作,這東西用kdtree可以隨便搞,弄個lazytag就可以了。

一堆除錯用的程式碼,所以看起來很長。

#include <bits/stdc++.h>

//#include <conio.h>

using namespace std;

typedef long long ll;
typedef double db;

const int
inf=0x3f3f3f3f; int getint() { int f=1,g=0;char c=getchar(); while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar(); return f*g; } const int maxn=100005; const int mod=1000000007; int dim; int n,m; struct node{ int
d[2]; int max[2]; int min[2]; int l,r; int tag; int color; int& operator [] (const unsigned int& num) { return d[num]; } bool operator < (const node& no)const { return d[dim]<no.d[dim]; } bool operator == (const node& no)const { return
d[0]==no.d[0] && d[1]==no.d[1]; } }; node p[maxn]; int root; struct Kdtree{ node t[maxn]; #define lc t[x].l #define rc t[x].r #define ls t[t[x].l] #define rs t[t[x].r] void update(int x) { t[x].min[0]=t[x].max[0]=t[x][0]; t[x].min[1]=t[x].max[1]=t[x][1]; if(lc) { t[x].min[0]=min(t[x].min[0],ls.min[0]); t[x].max[0]=max(t[x].max[0],ls.max[0]); t[x].min[1]=min(t[x].min[1],ls.min[1]); t[x].max[1]=max(t[x].max[1],ls.max[1]); } if(rc) { t[x].min[0]=min(t[x].min[0],rs.min[0]); t[x].max[0]=max(t[x].max[0],rs.max[0]); t[x].min[1]=min(t[x].min[1],rs.min[1]); t[x].max[1]=max(t[x].max[1],rs.max[1]); } } void push_down(int x) { if(!x || !t[x].tag)return; t[x].color=t[x].tag; ls.tag=rs.tag=t[x].tag; t[x].tag=0; } #define mid (l+r>>1) int build(int l,int r,int now) { dim=now; nth_element(p+l,p+mid,p+r+1); int x=mid; t[x].color=1; for(int i=0;i<2;i++) { t[x].min[i]=t[x].max[i]=t[x][i]=p[x][i]; } if(l<mid)lc=build(l,mid-1,now^1); if(r>mid)rc=build(mid+1,r,now^1); update(x); return x; } #undef mid node T1,T2; int col; void setcolor(int x) { if(!x)return; push_down(x); if(t[x].min[0]>T2[0] || t[x].max[0]<T1[0] || t[x].min[1]>T2[1] || t[x].max[1]<T1[1])return; if(t[x].min[0]>=T1[0] && t[x].max[0]<=T2[0] && t[x].min[1]>=T1[1] && t[x].max[1]<=T2[1]) { t[x].tag=col; return; } if(t[x][0]>=T1[0] && t[x][0]<=T2[0] && t[x][1]>=T1[1] && t[x][1]<=T2[1])t[x].color=col; setcolor(lc);setcolor(rc); } node T; int getcolor(int x) { push_down(x); if(T[0]<t[x].min[0] || T[0]>t[x].max[0] || T[1]<t[x].min[1] || T[1]>t[x].max[1])return 0; if(t[x]==T)return t[x].color; return getcolor(lc)+getcolor(rc); } void set(int x,int y,int xx,int yy,int co) { T1[0]=x;T1[1]=y; T2[0]=xx;T2[1]=yy; col=co; setcolor(root); } int query(int x,int y) { T[0]=x;T[1]=y; return getcolor(root); } void init() { memset(t,0,sizeof t); memset(p,0,sizeof p); root=0; } void run(int x) { if(!x)return; run(lc); printf("(%d,%d)->(%d,%d):%d(%d)(%d,%d)\n",t[x].min[0],t[x].min[1],t[x].max[0],t[x].max[1],t[x].color,t[x].tag,t[x][0],t[x][1]); run(rc); } #undef lc #undef rc #undef ls #undef rs }kdtree; vector<int> g[maxn]; void addedge(int from,int to) { g[from].push_back(to); g[to].push_back(from); } int dep[maxn]; int st[maxn]; int ed[maxn]; int ind; int father[maxn]; void dfs(int x) { st[x]=++ind; for(int i=0;i<g[x].size();i++) { int to=g[x][i]; if(father[x]==to)continue; dep[to]=dep[x]+1; dfs(to); } ed[x]=ind; } int main() { // freopen("in.txt","r",stdin); int T=getint(); while(T--) { for(int i=0;i<maxn;i++)g[i].clear(); kdtree.init(); ind=0; n=getint(); int temp=getint(); m=getint(); for(int i=2;i<=n;i++) { father[i]=getint(); addedge(i,father[i]); } dep[1]=1; dfs(1); /* for(int i=1;i<=n;i++) { printf("%d ",st[i]); } puts(""); for(int i=1;i<=n;i++) { printf("%d ",ed[i]); } puts(""); for(int i=1;i<=n;i++) { printf("%d ",dep[i]); } puts(""); */ for(int i=1;i<=n;i++) { p[i][0]=st[i]; p[i][1]=dep[i]; } root=kdtree.build(1,n,0); /* kdtree.run(root); puts(""); getch(); */ int x,y; int opt; ll ans=0; for(int i=1;i<=m;i++) { x=getint(); y=getint(); opt=getint(); if(!opt) { ll t=kdtree.query(st[x],dep[x]); //printf("%d\n",t); ans+=(ll)t*(ll)i; ans%=mod; } else { /* printf("We are painting (%d,%d)->(%d,%d):%d\n",st[x],dep[x],ed[x],dep[x]+y,opt); getch(); */ kdtree.set(st[x],dep[x],ed[x],dep[x]+y,opt); } /* kdtree.run(root); puts(""); getch(); */ } printf("%d\n",ans); } return 0; }