zoukankan      html  css  js  c++  java
  • BZOJ 4538: [Hnoi2016]网络 [整体二分]

    4538: [Hnoi2016]网络

    题意:一棵树,支持添加一条u到v权值为k的路径,删除之前的一条路径,询问不经过点x的路径的最大权值


    考虑二分

    整体二分最大权值,如果(k in [mid+1,r])中的路径有不经过x的,那么这个询问的答案在([mid+1,r])

    链修改,点查询( ightarrow)点修改,子树查询,方法是(u,v +1 ; lca,fa[lca] -1)

    用树状数组就可以完成

    这里的整体二分不需要对每个询问保存当前贡献,因为每次只需要考虑一段的贡献

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define fir first
    #define sec second
    const int N=2e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    
    int n, Q, id[N], mp[N], t1[N], t2[N], ans[N];
    struct meow{int op, u, v, k, t, x;} q[N];
    
    struct edge{int v, ne;}e[N-1];
    int cnt=1, h[N];
    inline void ins(int u, int v) {
    	e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
    	e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
    }
    namespace tr {
    	pair<int, int> dfn[N];
    	int fa[N], deep[N], dfc, tot, pos[N], f[N<<1][18];
    	void dfs(int u) {
    		dfn[u].fir = ++dfc; 
    		f[++tot][0] = u;
    		pos[u] = tot;
    		for(int i=h[u];i;i=e[i].ne) 
    			if(e[i].v != fa[u]) {
    				fa[e[i].v] = u;
    				deep[e[i].v] = deep[u]+1;
    				dfs(e[i].v);
    				f[++tot][0] = u;
    			}
    		dfn[u].sec = dfc;
    	}
    	int log[N];
    	inline int min(int x, int y) {return deep[x] < deep[y] ? x : y;}
    	void init() {
    		dfs(1);
    		//for(int i=1; i<=tot; i++) printf("%d ", f[i][0]); puts("");
    		for(int j=1; j<=17; j++) 
    			for(int i=1; i+(1<<j)-1<=tot; i++) 
    				f[i][j] = min(f[i][j-1], f[i+(1<<(j-1))][j-1]);// printf("f %d %d  %d
    ",i,j,f[i][j]);
    
    		log[1]=0; for(int i=2; i<=tot; i++) log[i] = log[i>>1]+1;
    	}
    	inline int lca(int x, int y) {
    		x = pos[x], y = pos[y]; if(x>y) swap(x, y);
    		int t = log[y-x+1];
    		return min(f[x][t], f[y-(1<<t)+1][t]);
    	}
    } using tr::lca; using tr::fa; using tr::dfn;
    
    namespace bit {
    	int c[N], T, t[N];
    	inline void ini() {T++;}
    	inline void add(int p, int v) {
    		for(; p<=n; p+=p&-p) { 
    			if(t[p] == T) c[p] += v;
    			else t[p] = T, c[p] = v;
    		}
    	}
    	inline int sum(int p) {
    		int ans=0; 
    		for(; p; p-=p&-p) if(t[p] == T) ans += c[p];
    		return ans;
    	}
    	inline int sum(int l, int r) {return sum(r) - sum(l-1);}
    	inline void cha(int id, int flag) {
    		int u=q[id].u, v=q[id].v, p=lca(u, v); //printf("uvp %d %d %d
    ", u, v, p);
    		add(dfn[u].fir, flag); add(dfn[v].fir, flag); 
    		add(dfn[p].fir, -flag); if(fa[p]) add(dfn[ fa[p] ].fir, -flag);
    	}
    } using bit::sum; using bit::cha;
    
    void cdq(int l, int r, int ql, int qr) { //printf("cdq [%d, %d]  %d %d
    ",l, r, ql, qr);
    	if(l==r) {
    		for(int i=ql; i<=qr; i++) if(q[id[i]].op == 3) ans[ id[i] ] = l;
    		return;
    	}
    
    	int mid = (l+r)>>1, p1=0, p2=0; //printf("mid %d
    ", mid);
    	bit::ini();
    	int now=0;
    	for(int i=ql; i<=qr; i++) { 
    		int _=i; i=id[i]; //printf("i-------- %d %d  %d
    ",_,i, q[i].op);
    		if(q[i].op == 1) { //printf("k %d
    ", q[i].k);
    			if(q[i].k > mid) cha(i, 1), now++, t2[++p2] = i;
    			else t1[++p1] = i;
    		} else if(q[i].op == 2) {
    			if(q[ q[i].t ].k > mid) cha(q[i].t, -1), now--, t2[++p2] = i;
    			else t1[++p1] = i;
    		} else { 
    			int x = q[i].x, cnt = sum(dfn[x].fir, dfn[x].sec); //printf("hi que %d  %d %d
    ", x, cnt, now);
    			if(cnt < now) t2[++p2] = i;
    			else t1[++p1] = i;
    		}
    		i=_;
    	}
    	for(int i=1; i<=p1; i++) id[ql+i-1] = t1[i];
    	for(int i=1; i<=p2; i++) id[ql+p1+i-1] = t2[i];
    	cdq(l, mid, ql, ql+p1-1); cdq(mid+1, r, ql+p1, qr);
    }
    
    int main() {
    	//freopen("in", "r", stdin);
    	freopen("network_tenderRun.in", "r", stdin);
    	freopen("network_tenderRun.out", "w", stdout);
    	n=read(); Q=read();
    	for(int i=1; i<n; i++) ins(read(), read());
    	for(int i=1; i<=Q; i++) {
    		q[i].op = read()+1;
    		if(q[i].op == 1) q[i].u=read(), q[i].v=read(), mp[++mp[0]] = q[i].k=read();
    		else if(q[i].op == 2) q[i].t=read();
    		else q[i].x=read();
    		id[i]=i;
    	}
    	sort(mp+1, mp+mp[0]+1); mp[0] = unique(mp+1, mp+mp[0]+1) - mp - 1;
    	for(int i=1; i<=Q; i++) if(q[i].op == 1) q[i].k = lower_bound(mp+1, mp+mp[0]+1, q[i].k) - mp;// printf("k %d  %d
    ", i, q[i].k);
    	tr::init(); 
    	//for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) printf("lca %d %d  %d
    ",i,j,lca(i, j));
    	cdq(0, mp[0], 1, Q); 
    	for(int i=1; i<=Q; i++) if(q[i].op == 3) printf("%d
    ", ans[i] ? mp[ans[i]] : -1);
    }
    
  • 相关阅读:
    devel包
    Tomcat性能调优
    详述Oracle RAC的五大优势及其劣势
    Oracle实例内存(SGA和PGA)调整
    ubuntu upstart启动流程分析
    Python爬虫示例
    Tcp连接的七次握手浅析
    Apache的prefork模式和worker模式
    减少mysql主从数据同步延迟
    Ubuntu14.04 64bit安装Android-Studio
  • 原文地址:https://www.cnblogs.com/candy99/p/6698554.html
Copyright © 2011-2022 走看看