P3258 [JLOI2014]松鼠的新家 树链剖分
这个题就是一道树剖板子题,就是每走一步就把所有的经过点加一就行了。还有,我的树剖板子没问题!!!谁知道为什么板子T3个点!我不管了!反正这道题正常写A了。
题干:
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。 松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致**重复走很多房间,懒惰的**不停地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。 **是个馋家伙,立马就答应了。现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。 因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。 输入输出格式 输入格式: 第一行一个整数n,表示房间个数第二行n个整数,依次描述a1-an 接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。 输出格式: 一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让**有糖果吃。 输入输出样例 输入样例#1: 复制 5 1 4 5 3 2 1 2 2 4 2 3 4 5 输出样例#1: 复制 1 2 1 2 1 说明 2<= n <=300000
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 300010; struct node { int l,r,nxt; }a[2 * N]; int n,len = 0,lst[N]; int A[N],tree[4 * N]; void add(int x,int y) { a[++len].l = x; a[len].r = y; a[len].nxt = lst[x]; lst[x] = len; } int f[N],dep[N],son[N],siz[N],id[N],rk[N]; int tp[N],cnt = 0,lazy[4 * N],vis[N]; void dfs1(int u,int fa,int depth) { f[u] = fa; siz[u] = 1; dep[u] = depth; for(int k = lst[u];k;k = a[k].nxt) { int y = a[k].r; if(y == fa) continue; dfs1(y,u,depth + 1); siz[u] += siz[y]; if(!son[u] || siz[son[u]] < siz[y]) son[u] = y; } } void dfs2(int u,int t) { vis[u] = 1; tp[u] = t; id[u] = ++cnt; rk[cnt] = u; if(!son[u]) return; dfs2(son[u],t); for(int k = lst[u];k;k = a[k].nxt) { int y = a[k].r; if(y == son[u] || y == f[u] || vis[y] == 1) continue; dfs2(y,y); } } void push_down(int o,int l,int r) { if(lazy[o] != 0) { int mid = (l + r) >> 1; tree[o << 1] += (mid - l + 1) * lazy[o]; tree[o << 1 | 1] += (r - mid) * lazy[o]; lazy[o << 1] += lazy[o]; lazy[o << 1 | 1] += lazy[o]; lazy[o] = 0; } } void update(int o,int l,int r,int x,int y) { int mid = (l + r) >> 1; if(l == x && r == y) { tree[o] += (r - l + 1); lazy[o] += 1; return; } push_down(o,l,r); if(mid >= y) update(o << 1,l,mid,x,y); else if(mid < x) update(o << 1 | 1,mid + 1,r,x,y); else { update(o << 1,l,mid,x,mid); update(o << 1 | 1,mid + 1,r,mid + 1,y); } tree[o] = tree[o << 1] + tree[o << 1 | 1]; } void update2(int x,int y) { while(tp[x] != tp[y]) { if(dep[tp[x]] < dep[tp[y]]) swap(x,y); update(1,1,n,id[tp[x]],id[x]); x = f[tp[x]]; } if(id[x] > id[y]) swap(x,y); update(1,1,n,id[x],id[y]); } int query(int o,int l,int r,int id) { if(l == r) return tree[o]; push_down(o,l,r); int mid = (l + r) >> 1; if(id <= mid) return query(o << 1,l,mid,id); else return query(o << 1 | 1,mid + 1,r,id); } int main() { read(n); duke(i,1,n) read(A[i]); duke(i,1,n - 1) { int x,y; read(x);read(y); add(x,y); add(y,x); } dfs1(1,0,0); dfs2(1,0); /*duke(i,1,n) printf("%d %d\n",id[i],tp[i]);*/ // printf("QAQ\n"); duke(i,1,n - 1) update2(A[i],A[i + 1]); duke(i,1,n) { int p = query(1,1,n,id[i]); if(A[1] != i) p -= 1; printf("%d\n",p); } return 0; }
顺便附赠树剖板子:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const int INF = 1 << 30; const int N = 200005; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct edge { int nxt,r; } e[4 * N]; int n,m,r,cnt; int a[N],lst[N],p; int f[N],d[N],siz[N],son[N],rk[N]; int top[N],id[N],tree[4 * N]; int lazy[4 * N],len = 0; //id新编号dfs序 void add(int x,int y) { e[++len].nxt = lst[x]; e[len].r = y; lst[x] = len; } void dfs1(int u,int fa,int depth) { f[u] = fa; d[u] = depth; siz[u] = 1; for(int k = lst[u];k;k = e[k].nxt) { int y = e[k].r; if(y == fa) continue; dfs1(y,u,depth + 1); siz[u] += siz[y]; if(siz[y] > siz[son[u]] || !son[u]) { son[u] = y; } } } void dfs2(int u,int t) { top[u] = t; id[u] = ++cnt; rk[cnt] = u; if(!son[u]) return; dfs2(son[u],t); for(int k = lst[u];k;k = e[k].nxt) { int y = e[k].r; if(y != son[u] && y != f[u]) dfs2(y,y); } } void push_down(int o,int l,int r) { if(lazy[o]) { lazy[o << 1] += lazy[o]; lazy[o << 1] %= p; lazy[o << 1 | 1] += lazy[o]; lazy[o << 1 | 1] %= p; int len = (r - l + 1); tree[o << 1] += lazy[o] * (len - (len >> 1)); tree[o << 1 | 1] += lazy[o] * (len >> 1); tree[o << 1] %= p; tree[o << 1 | 1] %= p; lazy[o] = 0; } } void build(int o,int l,int r) { if(l == r) { tree[o] = a[rk[l]]; tree[o] %= p; return; } int mid = (l + r) >> 1; build(o << 1,l,mid); build(o << 1 | 1,mid + 1,r); tree[o] = tree[o << 1] + tree[o << 1 | 1]; tree[o] %= p; } void up_num(int o,int l,int r,int x,int y,int w) { if(l == x && r == y) { tree[o] += w * (l - r + 1); tree[o] %= p; lazy[o] += w; lazy[o] %= p; return; } push_down(o,l,r); int mid = (l + r) >> 1; if(mid < x) up_num(o << 1 | 1,mid + 1,r,x,y,w); else if(mid >= y) up_num(o << 1,l,mid,x,y,w); else { up_num(o << 1,l,mid,x,mid,w); up_num(o << 1 | 1,mid + 1,r,mid + 1,y,w); } tree[o] = tree[o << 1] + tree[o << 1 | 1]; tree[o] %= p; } int query(int o,int l,int r,int x,int y) { if(l == r && x == y) { return tree[o]; } push_down(o,l,r); int mid = (l + r) >> 1; if(mid >= y) return query(o << 1,l,mid,x,y); else if(mid < x) return query(o << 1 | 1,mid + 1,r,x,y); else { return (query(o << 1,l,mid,x,mid) + query(o << 1 | 1,mid + 1,r,mid + 1,y)) % p; } } int pathquery(int x,int y) { int ans = 0; while(top[x] != top[y]) { if(d[top[x]] < d[top[y]]) swap(x,y); ans += query(1,1,n,id[top[x]],id[x]); ans %= p; x = f[top[x]]; } if(d[x] > d[y]) swap(x,y); ans += query(1,1,n,id[x],id[y]); ans %= p; return ans; } void pathupdate(int x,int y,int c) { // int fx = top[x],fy = top[y]; while(top[x] != top[y]) { if(d[top[x]] < d[top[y]]) swap(x,y); up_num(1,1,n,id[top[x]],id[x],c); x = f[top[x]]; // update(id[x]) } if(d[x] > d[y]) swap(x,y); up_num(1,1,n,id[x],id[y],c); } int main() { read(n);read(m);read(r);read(p); duke(i,1,n) read(a[i]); duke(i,1,n - 1) { int x,y; read(x);read(y); add(x,y); add(y,x); } cnt = 0; dfs1(r,0,1); dfs2(r,r); cnt = 0; build(1,1,n); duke(i,1,m) { int op,x,y,z; read(op); if(op == 1) { read(x);read(y);read(z); pathupdate(x,y,z); } else if(op == 2) { read(x);read(y); printf("%d\n",pathquery(x,y)); } else if(op == 3) { read(x);read(z); // cout<<x<<endl; up_num(1,1,n,id[x],id[x] + siz[x] - 1,z); } else { read(x); printf("%d\n",query(1,1,n,id[x],id[x] + siz[x] - 1)); } } return 0; } /* 5 2 24 3 7 8 0 2 5 1 1 4 2 2 2 5 5 1 3 1 3 */
只想找一个不会伤害我的人