【NOIP2017提高A组集训10.28】图

来源:互联网 发布:软件测试工资待遇2017 编辑:程序博客网 时间:2024/05/17 10:28

Description:

有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x的边,那么这个图仍是一个连通图,如果只保留权值形如k-x的边,这个图也依然是一个连通图。
给出q组询问,每组询问给出x的值,问此时这个无向连通图的最小生成树权值是多少。

1<=n,q<=100000 , n-1<=A,B<=200000, 0<=k<=10^9 , -10^9<=v<=10^9

题解:

这题考场就差那么一点点就想出来了。

题目都告诉你了A、B两个都可以生成一颗最小生成树。
那一定是对两个都建最小生成树,然后把另外一棵的边从小到大依次插入到这棵中,因为如果是其它边更优,那么这棵最小生成树一定会包含这条边,解释不清,需要感受。

插入到这棵树中,会形成一个环,那么把环上最大的边删掉,如果这条边是k1+x,当前这条是k2-x,那么当v>=(k2-k1)/2,k2-x这条边就会在最优的最小生成树上,答案就可以变小。
所以对所有(k2-k1)/2排个序,读入v二分一下即可算出答案。

加边删边lct维护。

Code:

#include<cstdio>#include<cstring>#include<algorithm>#define ll long long#define min(a, b) ((a) < (b) ? (a) : (b))#define max(a, b) ((a) > (b) ? (a) : (b)) #define fo(i, x, y) for(int i = x; i <= y; i ++)using namespace std;const int N = 3e5 + 50;int z[N], te;int fa[N], t[N][2], pf[N], rev[N], dd[N], mx[N];int lr(int x) {return t[fa[x]][1] == x;}void fan(int x) {if(x) swap(t[x][0], t[x][1]), rev[x] ^= 1;}void down(int x) {if(x && rev[x]) fan(t[x][0]), fan(t[x][1]), rev[x] = 0;}void update(int x) {    if(!x) return;    mx[x] = x;    mx[x] = z[mx[t[x][0]]] > z[mx[x]] ? mx[t[x][0]] : mx[x];    mx[x] = z[mx[t[x][1]]] > z[mx[x]] ? mx[t[x][1]] : mx[x];}void xc(int x) {    for(; x; x = fa[x]) dd[++ dd[0]] = x;    for(; dd[0]; dd[0] --) down(dd[dd[0]]);}void rotate(int x) {    int y = fa[x], k = lr(x);    t[y][k] = t[x][!k]; if(t[x][!k]) fa[t[x][!k]] = y;    fa[x] = fa[y]; if(fa[y]) t[fa[y]][lr(y)] = x;        t[x][!k] = y; fa[y] = x; pf[x] = pf[y];    update(y); update(x);}void splay(int x, int y) {    xc(x);    while(fa[x] != y) {        if(fa[fa[x]] != y)            if(lr(x) == lr(fa[x])) rotate(fa[x]); else rotate(x);        rotate(x);    }}void access(int x) {    for(int y = 0; x; update(x), y = x, x = pf[x]) {        splay(x, 0); fa[t[x][1]] = 0; pf[t[x][1]] = x;        t[x][1] = y; fa[y] = x; pf[y] = 0;    }    }void makeroot(int x) {    access(x); splay(x, 0); fan(x);}void link(int x, int y) {    makeroot(x); pf[x] = y; access(x);}void cut(int x, int y) {    makeroot(x); access(y); splay(y, 0);    t[y][0] = fa[x] = pf[x] = 0;    update(y);}int n, A, B, q;struct edge {    int u, v, k;}a[N * 2], b[N * 2];bool rank(edge a, edge b) {    return a.k < b.k;}int f[N];int find(int x) {    return f[x] == x ? x : (f[x] = find(f[x]));}void BT(edge *a, int A) {    sort(a + 1, a + A + 1, rank);    fo(i, 1, n) f[i] = i;    int tot = 0;    fo(i, 1, A) {        int x = a[i].u, y = a[i].v, k = a[i].k;        if(find(x) != find(y)) {            f[f[x]] = f[y];            a[++ tot] = a[i];        }        if(tot == n - 1) break;    }}struct node {    int x; ll y;} d[N];bool rank_d(node a, node b) {return a.x < b.x;}int main() {    freopen("graph.in", "r", stdin);    freopen("graph.out", "w", stdout);    scanf("%d %d %d %d", &n, &A, &B, &q);    fo(i, 1, A) scanf("%d %d %d", &a[i].u, &a[i].v, &a[i].k);    fo(i, 1, B) scanf("%d %d %d", &b[i].u, &b[i].v, &b[i].k);    BT(a, A); BT(b, B);    fo(i, 0, n) z[i] = -2e9;    ll sumk = 0;    int te = n;    fo(i, 1, n - 1) {        int x = a[i].u, y = a[i].v, k = a[i].k;        sumk += k;        te ++;        z[te] = k;        link(x, te); link(y, te);    }    int d0 = 0;    fo(i, 1, n - 1) {        int x = b[i].u, y = b[i].v, k = b[i].k;        makeroot(x); access(y); splay(y, 0);        int mb = mx[y];        if(mb > n + n - 1 || mb <= n) continue;        int x1 = a[mb - n].u, y1 = a[mb - n].v, k1 = a[mb - n].k;        cut(x1, mb); cut(y1, mb);        te ++; z[te] = -2e9;        link(x, te); link(y, te);        d[++ d0].x = (k - k1 + 1) / 2; d[d0].y = k - k1;    }    sort(d + 1, d + d0 + 1, rank_d);    fo(i, 2, d0) d[i].y += d[i - 1].y;    fo(ii, 1, q) {        int u; scanf("%d", &u);        int ans = 0;        for(int l = 1, r = d0; l <= r; ) {            int m = l + r >> 1;            if(d[m].x <= u)                ans = m, l = m + 1; else r = m - 1;        }        printf("%lld\n", sumk + d[ans].y + (ll)(n - 1 - ans * 2) * u);    }}
阅读全文
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 逗游下载速度慢怎么办 电推剪刀不锋利怎么办 白衣服洗得发黄怎么办 腰突然闪了很痛怎么办 一蹲下膝盖就疼怎么办 蹲久了膝盖疼怎么办 怀孕了外阴痒怎么办啊 我老婆出轨了我该怎么办 老婆有外遇我该怎么办 纸卡在打印机里怎么办 脸上的颧骨太高怎么办? 脸磕了一下淤血怎么办 腿磕到了有淤血怎么办 屁股摔了很疼怎么办 摔了脚踝肿了怎么办 扭了脚肿起来了怎么办 发际线低额头窄怎么办 档案写错了涂改怎么办 当时档案写错了怎么办 档案内容写错了怎么办 高中档案写错了怎么办 上大学档案丢了怎么办 u盘总提示格式化怎么办 黑莓手机id锁了怎么办 美图手机进水了怎么办 球兰叶子发黄软怎么办 蟹爪莲叶子发红怎么办 保险箱没电了打不开怎么办 宁波臭冬瓜酸的怎么办 甜酒酿做了酸了怎么办 孕妇喝了醪糟汤怎么办 鱼侧翻但又没死怎么办 原汁机盖子卡死怎么办 惠人原汁机坏了怎么办 泡芙鸡蛋加多了怎么办 淡奶油打过了怎么办 淡奶油打发过了怎么办 雷神锤子被捏碎怎么办 私处毛很多很黑怎么办 脸上长黑色的毛怎么办 十字军之王2毁容怎么办