洛谷P3806 點分治1
阿新 • • 發佈:2018-12-12
如果給你一個查詢 那就是裸的點分治 但是給你m個查詢 你該咋辦呢
不妨在查詢之前先處理好所有可能出現的邊 然後線上查詢就行
總根進行++操作 消除子樹的影響 進行--操作
具體可以看程式碼吧
/* luogu 3806 */ #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <iostream> #include <stack> #include <set> #include <map> #include <sstream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAX_N = 100024; int f[MAX_N],siz[MAX_N]; struct edge{ int next,v,dis; }e[MAX_N<<1]; int eid,p[MAX_N],use[MAX_N],Siz,rt,cnt,k,ask[MAX_N],ANS[MAX_N],m,sum[MAX_N]; int d[10000005]; inline int read() { int date = 0,m = 1; char ch = 0; while(ch!='-'&&(ch<'0'||ch>'9')) ch = getchar(); if(ch=='-') { m = -1; ch = getchar(); } while(ch>='0' && ch<='9') { date = date*10+ch-'0'; ch = getchar(); } return date*m; } inline void write(ll qw) { if(qw<0) { putchar('-'); qw = -qw; } if(qw>9) write(qw/10); putchar(qw%10+'0'); } void init(){ memset(p,-1,sizeof(p)); memset(use,0,sizeof(use)); rt = 0; eid = 0; } void Insert(int u,int v,int dis){ e[eid].v = v; e[eid].dis = dis; e[eid].next = p[u]; p[u] = eid++; } void get_rt(int u,int fa){//u為當前點,fa為父親節點 f[u] = 0, siz[u] = 1;//f表示這個點最大子樹的大小,siz是這個點子樹大小的和 for(int i = p[u];i!=-1;i = e[i].next){//列舉兒子 int y = e[i].v; if(use[y]||y==fa) continue;//use表示之前遍歷過了,這裡沒啥用 get_rt(y,u);//往下遍歷 f[u] = max(f[u],siz[y]);//更新f siz[u] += siz[y]; } f[u] = max(f[u],Siz - siz[u]);//Siz表示在現在這棵子樹中點的總數,開始時Siz=n,除了列舉的兒子所在的子樹外,還有一棵子樹是上面的那一堆,容斥原理 if(f[u]<f[rt]) rt = u;//更新root } void query(int u,int fa,int dis){ d[++cnt]=dis; for(int i = p[u];i!=-1;i=e[i].next){ int y = e[i].v; if(use[y]||y==fa) continue; query(y,u,dis+e[i].dis); } return ; } void solve(int u,int dis,int flag){ cnt = 0; query(u,0,dis); if(flag==1){ for(int i = 1;i<cnt;++i) for(int j = i+1;j<=cnt;j++){ sum[d[i]+d[j]]++; } } else { for(int i = 1;i<cnt;++i) for(int j = i+1;j<=cnt;j++) sum[d[i]+d[j]]--; } return; } void dfs(int u){//Divide use[u] = 1,solve(u,0,1); for(int i = p[u];i!=-1;i=e[i].next){ int y = e[i].v; if(use[y]) continue; solve(y,e[i].dis,0); Siz = siz[y],rt = 0; get_rt(y,u),dfs(rt); } return ; } int main(){ int n; n = read(),m = read(); init(); for(int i = 1;i<n;++i){ int a,b,dis; a = read(),b = read(),dis = read(); Insert(a,b,dis); Insert(b,a,dis); } f[0] = Siz = n; get_rt(1,0); dfs(rt); int opt; for(int i = 1;i<=m;++i){ opt = read(); if(sum[opt]) printf("AYE\n"); else printf("NAY\n"); } return 0; }