• luogu3384 【模板】树链剖分


    强烈推荐这篇文章,一下子就看懂AC了。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    struct Edge{
    	int too, nxt;
    }edge[200005];
    int n, m, r, p, uu, vv, ww, tt, w[100005], hea[100005], ecnt, dep[100005];
    int fa[100005], siz[100005], son[100005], idx[100005], cnt, wt[100005];
    int top[100005];
    void add_edge(int fro, int too){
    	edge[++ecnt].nxt = hea[fro];
    	edge[ecnt].too = too;
    	hea[fro] = ecnt;
    }
    void dfs1(int x, int f){
    	dep[x] = dep[f] + 1;
    	fa[x] = f;
    	siz[x] = 1;
    	int maxSon=-1;
    	for(int i=hea[x]; i; i=edge[i].nxt){
    		int t=edge[i].too;
    		if(t==f)	continue;
    		dfs1(t, x);
    		siz[x] += siz[t];
    		if(siz[t]>maxSon){
    			son[x] = t;
    			maxSon = siz[t];
    		}
    	}
    }
    void dfs2(int x, int topf){
    	idx[x] = ++cnt;
    	wt[cnt] = w[x] % p;
    	top[x] = topf;
    	if(!son[x])	return ;
    	dfs2(son[x], topf);
    	for(int i=hea[x]; i; i=edge[i].nxt){
    		int t=edge[i].too;
    		if(t==fa[x] || t==son[x])	continue;
    		dfs2(t, t);
    	}
    }
    struct SFT{
    	int sum[400005];
    	int tag[400005];
    	void build(int o, int l, int r){
    		if(l==r)	sum[o] = wt[l];
    		else{
    			int mid=(l+r)>>1;
    			int lson=o<<1;
    			int rson=lson|1;
    			if(l<=mid)	build(lson, l, mid);
    			if(mid<r)	build(rson, mid+1, r);
    			sum[o] = (sum[lson] + sum[rson]) % p;
    		}
    	}
    	void pushdown(int o, int l, int r, int lson, int rson, int mid){
    		tag[lson] = (tag[lson] + tag[o]) % p;
    		tag[rson] = (tag[rson] + tag[o]) % p;
    		sum[lson] = (sum[lson] + (mid-l+1) * tag[o] % p) % p;
    		sum[rson] = (sum[rson] + (r-mid) * tag[o] % p) % p;
    		tag[o] = 0;
    	}
    	void update(int o, int l, int r, int x, int y, int k){
    		if(l>=x && r<=y){
    			sum[o] = (sum[o] + (r-l+1) * k % p) % p;
    			tag[o] = (tag[o] + k) % p;
    		}
    		else{
    			int mid=(l+r)>>1;
    			int lson=o<<1;
    			int rson=lson|1;
    			if(tag[o])	pushdown(o, l, r, lson, rson, mid);
    			if(x<=mid)	update(lson, l, mid, x, y, k);
    			if(mid<y)	update(rson, mid+1, r, x, y, k);
    			sum[o] = (sum[lson] + sum[rson]) % p;
    		}
    	}
    	int query(int o, int l, int r, int x, int y){
    		if(l>=x && r<=y)	return sum[o];
    		else{
    			int mid=(l+r)>>1;
    			int lson=o<<1;
    			int rson=lson|1;
    			int ans=0;
    			if(tag[o])	pushdown(o, l, r, lson, rson, mid);
    			if(x<=mid)	ans = (ans + query(lson, l, mid, x, y)) % p;
    			if(mid<y)	ans = (ans + query(rson, mid+1, r, x, y)) % p;
    			return ans;
    		}
    	}
    }sgt;
    void updRange(int uu, int vv, int ww){
    	ww %= p;
    	while(top[uu]!=top[vv]){
    		if(dep[top[uu]]<dep[top[vv]])	swap(uu, vv);
    		sgt.update(1, 1, n, idx[top[uu]], idx[uu], ww);
    		uu = fa[top[uu]];
    	}
    	if(dep[uu]>dep[vv])	swap(uu, vv);
    	sgt.update(1, 1, n, idx[uu], idx[vv], ww);
    }
    int queryRange(int uu, int vv){
    	int ans=0;
    	while(top[uu]!=top[vv]){
    		if(dep[top[uu]]<dep[top[vv]])	swap(uu, vv);
    		ans = (ans + sgt.query(1, 1, n, idx[top[uu]], idx[uu])) % p;
    		uu = fa[top[uu]];
    	}
    	if(dep[uu]>dep[vv])	swap(uu, vv);
    	ans = (ans + sgt.query(1, 1, n, idx[uu], idx[vv])) % p;
    	return ans;
    }
    int main(){
    	cin>>n>>m>>r>>p;
    	for(int i=1; i<=n; i++)
    		scanf("%d", &w[i]);
    	for(int i=1; i<n; i++){
    		scanf("%d %d", &uu, &vv);
    		add_edge(uu, vv);
    		add_edge(vv, uu);
    	}
    	dep[r] = 1;
    	dfs1(r, 0);
    	dfs2(r, r);
    	sgt.build(1, 1, n);
    	while(m--){
    		scanf("%d", &tt);
    		if(tt==1){
    			scanf("%d %d %d", &uu, &vv, &ww);
    			updRange(uu, vv, ww);
    		}
    		else if(tt==2){
    			scanf("%d %d", &uu, &vv);
    			printf("%d
    ", queryRange(uu, vv));
    		}
    		else if(tt==3){
    			scanf("%d %d", &uu, &ww);
    			sgt.update(1, 1, n, idx[uu], idx[uu]+siz[uu]-1, ww);
    		}
    		else{
    			scanf("%d", &uu);
    			printf("%d
    ", sgt.query(1, 1, n, idx[uu], idx[uu]+siz[uu]-1));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何优雅地「蜗居」?
    TCP三次链接和四次断开
    linux文件系统目录
    Linux sync命令的作用分析
    system()函数
    linux 端口设置结构体 struc
    Linux内核的三种调度策略
    setsid
    Android通过NTP服务器取得UTC标准时间
    fprintf输出到文件中,sprintf输出到字符串中. 如: fprintf(fp,"%s",name); fp为文件指针 sprintf(buff,"%s",name); buff为字符数组
  • 原文地址:https://www.cnblogs.com/poorpool/p/8146307.html
Copyright © 2020-2023  润新知