• 染色(dye)


    染色(dye)

    Description

    Serene 和 Achen 在玩染色游戏。Serene 和 Achen 站在一个 n 个点 m 条边的无向连通图中,在第 i 次玩染色游戏时,Serene 在 a_i,Achen 在 b_i,并且所有节点都变为白色,在这次游戏中,Serene 和 Achen 会走过一些边,并且把路途中经过的所有点染成黑色,她们一共需要把 k_i 个点染成黑色(一个点如 果被染多次只计算一次)。

    但是 Serene 和 Achen 不想太累,她们的劳累值是她们俩所经过的所有的边的最 大编号。Serene 想知道,每次玩染色游戏时 Serene 和 Achen 的最小的劳累值。

    Input

    一行两个整数 n,m

    接下来 m 行每行两个数 x_i,y_i 表示编号为 i 的边所连接的两个点

    接下来一行一个数 q,表示 Serene 和 Achen 做游戏的次数

    接下来 q 行每行两个数 a_i,b_i,k_i 表示 Serene 和 Achen 的初始位置和需要染成黑色的点数

    Output

    q 行,对于每次游戏输出最小劳累值。

    Sample Input

    5 6

    2 3

    4 5

    1 2

    1 3

    1 4

    1 5

    6

    2 4 3

    2 4 4

    2 4 5

    1 3 3

    1 3 4

    1 3 5

    Sample Output

    1

    2

    3

    1

    5

    5

    Hint

    对于 20%的数据,n,m,q<=500

    对于 60%的数据,n,m,q<=50000

    对于 100%的数据,n,m,q<=200000

    原题

    整体二分。

    二分的一个答案显然可以用并查集维护。

    若是每次暴力从头建并查集肯定会死亡TLE。

    于是用按秩合并的并查集,每次二分之后先往又区间走,往右走之后操作是往并查集里加。

    走完不得不往左走时,把之前操作的后一半撤销。为了撤销强行开了个栈存操作。

    然后奥妙地跑得比std快。

    正解是整体二分时不按dfs序做而是按bfs序做。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    const int N=400007;
    #define For(i,a,b) for(int i=(a);i<=(b);i++)
    #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    typedef long long LL;
    using namespace std;
    int n,m,q,fa[N],sz[N],ans[N];
    
    template<typename T>void read(T &x)  {
        char ch=getchar(); x=0; T f=1;
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    struct edge {
        int u,v,w;
    }e[N];
    
    struct node {
        int x,y,k,id;
    }qs[N],tp[N];
    
    int find(int x) { return x==fa[x]?x:find(fa[x]); }
    
    struct op {
        int x,fa,id;
        op(){}
        op(int x,int fa,int id):x(x),fa(fa),id(id){}
    }sta[N*18];
    int top;
    void solve(int l,int r,int ql,int qr,int f) {
        if(l>r||ql>qr) return ;
        if(l==r) {
            For(i,ql,qr) ans[qs[i].id]=l;
            return;
        }
        int mid=((l+r)>>1);
        int ll=ql-1,rr=qr+1;
        if(f) {
            For(i,l,mid) {
                int x=find(e[i].u),y=find(e[i].v);
                if(x!=y) {
                    if(sz[x]<=sz[y]) {
                        fa[x]=y,sz[y]+=sz[x];
                        sta[++top]=op(x,y,i);
                    }
                    else  {
                        fa[y]=x,sz[x]+=sz[y];
                        sta[++top]=op(y,x,i);
                    }
                }
            }
        }
        For(i,ql,qr) {
            int x=find(qs[i].x),y=find(qs[i].y);
            if((x==y&&sz[x]>=qs[i].k)||(x!=y&&sz[x]+sz[y]>=qs[i].k)) tp[++ll]=qs[i];
            else tp[--rr]=qs[i];
        }
        For(i,ql,qr) qs[i]=tp[i];
        solve(mid+1,r,rr,qr,1);
        Rep(i,top,1) {
            if(sta[i].id<=((l+mid)>>1)) break;
            int x=sta[i].x,f=sta[i].fa;
            fa[x]=x; sz[f]-=sz[x]; top--;
        }
        solve(l,mid,ql,ll,0);
    }
    
    #define DEBUG
    int main() {
    #ifdef DEBUG
        freopen("dye.in","r",stdin);
        freopen("dye.out","w",stdout);
    #endif
        read(n); read(m);
        For(i,1,m) {
            read(e[i].u); read(e[i].v); 
            e[i].w=i;
        }
        read(q);
        For(i,1,q) {
            read(qs[i].x); read(qs[i].y);
            read(qs[i].k); qs[i].id=i;
        }
        For(i,1,n) fa[i]=i,sz[i]=1;
        solve(1,m,1,q,1);
        For(i,1,q) printf("%d
    ",ans[i]);
        return 0;
    }
    /*
    5 6
    2 3
    4 5
    1 2
    1 3
    1 4
    1 5
    6
    2 4 3
    2 4 4
    2 4 5
    1 3 3
    1 3 4
    1 3 5
    */
    View Code

     

  • 相关阅读:
    【PHP内存泄漏案例】PHP对象递归引用造成内存泄漏
    【总结】/etc/rc.d/rc.local 与 /etc/profile .bash_profile .bashrc 文件执行顺序
    MySQL数据类型
    PHP通用分页(Pager)类
    【抚琴煮酒】我们的网站压力究竟在哪里?
    Linux/CentOS 服务安装/卸载,开机启动chkconfig命令详解|如何让MySQL、Apache开机启动?
    /etc/rc.d/rc与/etc/rc.d/init.d的关系
    PHP正则表达式30分钟入门教程
    数学之路-分布式计算-disco(4)
    数据库中存储日期的字段类型究竟应该用varchar还是datetime ?
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8570152.html
Copyright © 2020-2023  润新知