• 【BZOJ】1103: [POI2007]大都市meg


    http://www.lydsy.com/JudgeOnline/problem.php?id=1103

    题意:一棵n节点的树(1<=n<=250000),m条边(1<=m<=250000-1),权值为1,有n+m-1个操作:操作W u:询问u到根的权值和; 操作A u v,将边(u, v)的权值减去1

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=250005;
    int n, ihead[N], cnt;
    struct dat { int next, to; }e[N<<1];
    void add(int u, int v) {
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u;
    }
    int dep[N], tot, FF[N], LL[N];
    void dfs(int x, int fa) {
    	FF[x]=++tot;
    	for(int i=ihead[x]; i; i=e[i].next) if(e[i].to!=fa) dep[e[i].to]=dep[x]+1, dfs(e[i].to, x);
    	LL[x]=tot;
    }
    int c[N];
    void upd(int x, int s) { for(; x<=n; x+=x&-x) c[x]+=s; }
    int sum(int x) { int ret=0; for(; x; x-=x&-x) ret+=c[x]; return ret; }
    int main() {
    	scanf("%d", &n);
    	for(int i=0; i<n-1; ++i) { int u, v; scanf("%d%d", &u, &v); add(u, v); }
    	dfs(1, 0);
    	int m; scanf("%d", &m);
    	for(int k=0; k<m+n-1; ++k) {
    		int u, v;
    		char s[2];
    		scanf("%s%d", s, &u);
    		if(s[0]=='W') {
    			printf("%d
    ", sum(FF[u])+dep[u]); 
    		}
    		else {
    			scanf("%d", &v);
    			if(dep[u]<dep[v]) swap(u, v);
    			upd(FF[u], -1);
    			upd(LL[u]+1, 1);
    		}
    	}
    	return 0;
    }
    

      


    做过dfs序的应该都会吧...

    很显然,每次更改一条边,影响了深度大一点的节点的所有子树,询问就是询问1-当前点的权值和就行了

    所以我们维护一下dfs序和前缀和即可

  • 相关阅读:
    Python 爬虫
    Web 前端编程运维必备
    Docker 运维高级应用管理
    Python 运维之路
    Linux 运维之路
    8086汇编 中断
    8086汇编 rep 指令
    8086汇编 cmp 指令
    8089汇编 标志寄存器
    8086汇编 call 指令
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4216080.html
Copyright © 2020-2023  润新知