zoukankan      html  css  js  c++  java
  • [CTSC2008]网络管理 [整体二分]

    题面

    bzoj
    luogu

    所有事件按时间排序
    按值划分下放

    把每一个修改
    改成一个删除一个插入

    对于一个查询
    直接查这个段区间有多少合法点
    如果查询值大于等于目标值 进入左区间

    如果一个查询无解
    那么它要求第k大无解
    k > 路径长 用lca维护即可

    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #define Sqr(x) ((x)*(x))
    using namespace std;
    const int N = 8e4 + 5;
    const int inf = 1e8 + 5;
    struct Edge{
        int v, next;	
    }edge[N << 1];
    int head[N], esize;
    inline void addedge(int x, int y){
        edge[++esize] = (Edge){y, head[x]};
        head[x] = esize;	
    }
    struct Node{
        int t, x, y, w, d;
        bool type;	//0是插入 1是查询
    }node[N << 2], p1[N << 2], p2[N << 2];
    int n, m, nsize, a[N], ans[N];
    int tim, dfn[N], top[N], son[N], fa[N], size[N], rf[N], dep[N];
    bool flag[N];
    
    struct BIT{
    	int w[N];
    	void ins(int x, int d){while(x <= n){w[x] += d; x += x & -x;}}
    	int qry(int x){int res = 0; while(x){res += w[x]; x -= x & -x;} return res;}
    }bit;
    
    inline void addnode(int x1, int x2, int x3, int x4, int x5, bool x6){
    	++nsize, node[nsize].t = x1, node[nsize].x = x2, node[nsize].y = x3, 
    	node[nsize].w = x4, node[nsize].d = x5, node[nsize].type = x6;
    }
    
    void dfs1(int x, int ff){
    	dep[x] = dep[ff] + 1, size[x] = 1, fa[x] = ff;
    	for(int i = head[x], vv; ~i; i = edge[i].next){
    		vv = edge[i].v; if(vv == ff) continue;
    		dfs1(vv, x);
    		size[x] += size[vv];
    	    if(size[son[x]] < size[vv]) son[x] = vv;	
    	}
    }
    
    void dfs2(int x, int tp){
        top[x] = tp, dfn[x] = ++tim, rf[tim] = x;
        if(son[x]) dfs2(son[x], tp); else return;
    	for(int i = head[x], vv; ~i; i = edge[i].next){
    		vv = edge[i].v; if(vv == fa[x] || vv == son[x]) continue;
    	    dfs2(vv, vv);
    	}
    }
    
    int LCA(int x, int y){
        while(top[x] != top[y]){
    	    if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		x = fa[top[x]];
    	}	
    	return dep[x] < dep[y] ? x : y;
    }
    
    int qry(int x, int y){
        int res = 0;
        while(top[x] != top[y]){
    		if(dep[top[x]] < dep[top[y]]) swap(x, y);
    		res += bit.qry(dfn[x]) - bit.qry(dfn[top[x]] - 1);
    		x = fa[top[x]];
    	}	
    	if(dep[x] < dep[y]) swap(x, y); res += bit.qry(dfn[x]) - bit.qry(dfn[y] - 1);
    	return res;
    }
    
    void erfn(int L, int R, int l, int r){
    	if(L > R) return;
    	if(l == r){
    		for(int i = L; i <= R; ++i)
    			if(node[i].type && ~ans[node[i].t]) ans[node[i].t] = l;
    	    return ;	
    	}
    	int mid = l + ((r - l) >> 1);
    	int t1 = 0, t2 = 0;
    	for(int i = L; i <= R; ++i){
    	    if(node[i].type) {
    			int cnt = qry(node[i].x, node[i].y);
    			if(cnt >= node[i].w) p2[++t2] = node[i];
    			else node[i].w -= cnt, p1[++t1] = node[i];//第k大!!先减再复制!!
    		}
    		else {
    		    if(node[i].w <= mid) p1[++t1] = node[i];
    			else p2[++t2] = node[i], bit.ins(dfn[node[i].x], node[i].d);
    		}
    	}
    	for(int i = L; i <= R; ++i) 
    		if(!node[i].type && node[i].w > mid) 
    			bit.ins(dfn[node[i].x], -node[i].d);
    	for(int i = 1; i <= t1; ++i) node[L + i - 1] = p1[i];
    	for(int i = 1; i <= t2; ++i) node[L + t1 + i - 1] = p2[i];	
    	erfn(L, L + t1 - 1, l, mid); erfn(L + t1, R, mid + 1, r);
    }
    
    int main() {
    	memset(head, -1, sizeof(head));
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; ++i){
    		scanf("%d", &a[i]);
    		addnode(0, i, 0, a[i], 1, 0);
    	}
    	for(int i = 1, x, y; i < n; ++i){
    	    scanf("%d%d", &x, &y);
    	    addedge(x, y); addedge(y, x);	
    	} dfs1(1, 0); dfs2(1, 1);
    	for(int i = 1, x, y, z; i <= m; ++i){
    	    scanf("%d%d%d", &x, &y, &z); flag[i] = (bool)x; 
    		if(x){ 
    			int len = dep[y] + dep[z] - 2 * dep[LCA(y, z)] + 1;
    			if(x > len) ans[i] = -1;
    			else addnode(i, y, z, x, 0, 1);
    		}	
    	    else addnode(i, y, 0, a[y], -1, 0), addnode(i, y, 0, z, 1, 0), a[y] = z, ans[i] = -1;
    	}
    	erfn(1, nsize, 0, inf);
    	for(int i = 1; i <= m; ++i)
    		if(flag[i]){
    			if(ans[i] == -1) printf("invalid request!
    "); 
    			else printf("%d
    ", ans[i]);
    		} 
        //system("PAUSE");
        return 0;
    }
    
  • 相关阅读:
    视图
    Mysql事务
    子查询
    Mysql连表查询
    Mysql增删改查
    Mysql数据类型
    EntityFramwork 查询
    Git
    EntityFramework走马观花之CRUD(下)
    EntityFramework走马观花之CRUD(中)
  • 原文地址:https://www.cnblogs.com/hjmmm/p/10658258.html
Copyright © 2011-2022 走看看