ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

#3145. 「APIO 2019」桥梁

2019-06-27 14:52:15  阅读:214  来源: 互联网

标签:le int back st dep 2019 3145 APIO size


#3145. 「APIO 2019」桥梁

题目描述

圣彼得堡市内所有水路长度总和约 282 千米,市内水域面积占城市面积的 7%。——来自维基百科

圣彼得堡位于由 \(m\) 座桥梁连接而成的 \(n\) 个岛屿上。岛屿用 \(1\) 到 \(n\) 的整数编号,桥梁用 \(1\) 到 \(m\) 的整数编号。每座桥连接两个不同的岛屿。有些桥梁是在彼得大帝时代建造的,其中一些是近期建造的。这导致了不同的桥梁可能有不同的重量限制。更具体地,只有重量不超过 \(d_i\) 的汽车才能通过第 \(i\) 座桥梁。有时圣彼得堡的一些桥梁会进行翻新,但这并不一定会使桥梁承重变得更好,也就是说,进行翻新的桥梁的 \(d_i\) 可能会增加或减少。你准备开发一个产品,用于帮助公民和城市客人。目前,你开发的模块要能执行两种类型的操作:

\1. 将桥梁 \(b_j\) 的重量限制改为 \(r_j\)。

\2. 统计一辆重为 \(w_j\) 的汽车从岛屿 \(s_j\) 出发能够到达多少个不同的岛屿。

请你回答所有第二种操作的答案。

输入格式

第一行包含两个整数 \(n\) 和 \(m\)——表示圣彼得堡的岛屿数量与桥梁数量。

接下来 \(m\) 行,每行三个整数 \(u_i, v_i, d_i\)。第 \(i\) 行的整数描述了一座连接岛屿 \(u_i\) 和 \(v_i\),初始时重量限制为 \(d_i\) 的桥梁。

接下来一行一个整数 \(q\)——表示操作的数量。

接下来 \(q\) 行按顺序每行描述一个操作。

每行第一个整数 \(t_j\) 表示操作类型:

- 若 \(t_j = 1\),则该操作是第一种类型,该行接下来给定两个整数 \(b_j\) 和 \(r_j\),表示桥梁 \(b_j\) 的重量限制将变为 \(r_j\)。

- 若 \(t_j = 2\),则该操作是第二种类型,该行接下来给定两个整数 \(s_j\) 和 \(w_j\),表示一辆重为 \(w_j\) 的汽车将要从第 \(s_j\) 个岛屿出发。

输出格式

对于每个第二种类型的询问,输出一行一个整数表示答案。

数据范围与提示

对于全部数据,\(1\le n\le 5\times 10^4,0\le m\le 10^5,1\le q\le 10^5\)。保证 \(1\le u_i,v_i,s_j\le n,u_i\not =v_i,1\le d_i,r_j,w_j\le 10^9,1\le b_j\le m,t_j\in\{1,2\}\)。


我们把一次修改视作产生了两条不同的边,每条边都有一个存在的时间。

将操作序列分块,对每个块内的询问分别处理。将询问的\(w\)升序排列,将出现在这个块之前,并且在这个块之后再消失的边按\(w\)排序。依次处理询问时,依次加入这些边,用路径压缩的并查集。每一次询问时,对于结束时间在这个块内的边,我们暴力判断是否要加入,询问了之后再撤销。这部分用按秩合并的并查集。

复杂度\(O(m\sqrt{mlog(n)})\)

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 100005

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n,m,q;

const int blk=600;
int bel[N];
struct edge {
    int x,y,w;
    int l,r;
    bool operator <(const edge &a)const {return w>a.w;}
}e[N<<1];
bool cmpe(int a,int b) {
    return e[a].w>e[b].w;
}
int etot;
int lst[N];
int op[N];
int E[N],pos[N],w[N];
vector<int>que[N/blk+5];
bool cmp(int a,int b) {return w[a]>w[b];}

int fa[N],size[N],dep[N];
int Getf(int v) {return v==fa[v]?v:fa[v]=Getf(fa[v]);}

int Getf2(int v) {
    while(v!=fa[v]) v=fa[v];
    return v;
}

void Merge(int a,int b) {
    a=Getf(a),b=Getf(b);
    if(a==b) return ;
    fa[a]=b;
    size[b]+=size[a];
}

void Init() {for(int i=1;i<=n;i++) fa[i]=i,size[i]=1,dep[i]=1;}
vector<int>tem;
int L[N],R[N];
struct node {
    int x,size,dep;
    node() {}
    node(int _x,int _size,int _dep) {x=_x,size=_size,dep=_dep;}
};
vector<node>undo;
vector<int>st,st2;
int ans[N];
void Merge(vector<int>&a,vector<int>&b) {
    static vector<int>st;
    st.clear();
    int ta=0,tb=0;
    while(ta!=a.size()||tb!=b.size()) {
        if(ta==a.size()) st.push_back(b[tb]),tb++;
        else if(tb==b.size()) st.push_back(a[ta]),ta++;
        else if(e[a[ta]].w>e[b[tb]].w) st.push_back(a[ta]),ta++;
        else st.push_back(b[tb]),tb++;
    }
    a.clear();
    for(int i=0;i<st.size();i++) a.push_back(st[i]);
}
int main() {
    n=Get(),m=Get();
    for(int i=1;i<=m;i++) {
        e[i].x=Get(),e[i].y=Get(),e[i].w=Get();
    }
    q=Get();
    for(int i=1;i<=m;i++) {
        lst[i]=i;
        e[i].l=1,e[i].r=q;
    }
    etot=m;
    int x,y;
    for(int i=1;i<=q;i++) {
        op[i]=Get();
        x=Get(),y=Get();
        if(op[i]==1) {
            E[i]=++etot;
            e[E[i]]=e[lst[x]];
            e[E[i]].w=y;
            e[lst[x]].r=i-1;
            e[E[i]].l=i;
            e[E[i]].r=q;
            lst[x]=etot;
        } else {
            pos[i]=x,w[i]=y;
        }
    }
    sort(e+1,e+1+m);
    for(int i=1;i<=m;i++) if(e[i].r) st.push_back(i);
    for(int i=1;i<=q;i++) bel[i]=(i-1)/blk+1;
    for(int i=1;i<=bel[q];i++) L[i]=(i-1)*blk+1,R[i]=min(q,i*blk);
    for(int i=1;i<=q;i++) if(op[i]==2) que[bel[i]].push_back(i);
    
    for(int i=1;i<=bel[q];i++) {
        sort(que[i].begin(),que[i].end(),cmp);
        Init();
         
        tem.clear();
        for(int j=L[i];j<=R[i];j++) if(op[j]==1) tem.push_back(E[j]);
        int tag=0;
        for(int j=0;j<que[i].size();j++) {
            int now=que[i][j];
            while(tag<st.size()&&e[st[tag]].w>=w[now]) {
                if(e[st[tag]].r>=R[i]) {
                    Merge(e[st[tag]].x,e[st[tag]].y);
                } else if(e[st[tag]].r>=L[i]) tem.push_back(st[tag]);
                tag++;
            }
            for(int k=0;k<tem.size();k++) {
                int x=e[tem[k]].x,y=e[tem[k]].y;
                Getf(x),Getf(y);
            }
            undo.clear();
            for(int k=0;k<tem.size();k++) {
                int id=tem[k];
                if(e[id].l<=now&&now<=e[id].r&&e[id].w>=w[now]) {
                    int x=Getf2(e[id].x),y=Getf2(e[id].y);
                    if(x==y) continue ;
                    undo.push_back(node(x,size[x],dep[x]));
                    undo.push_back(node(y,size[y],dep[y]));
                    if(dep[x]>dep[y]) swap(x,y);
                    fa[x]=y;
                    size[y]+=size[x];
                    if(dep[x]==dep[y]) dep[y]++;
                }
            }
            ans[now]=size[Getf2(pos[now])];
            while(undo.size()) {
                node a=undo.back();
                undo.pop_back();
                fa[a.x]=a.x;
                size[a.x]=a.size;
                dep[a.x]=a.dep;
            }
        }
        st2.clear();
        for(int j=L[i];j<=R[i];j++) if(op[j]==1) st2.push_back(E[j]);
        sort(st2.begin(),st2.end(),cmpe);
        Merge(st,st2);
    }
    for(int i=1;i<=q;i++) if(ans[i]) {
        cout<<ans[i]<<"\n";
    }
    return 0;
}

标签:le,int,back,st,dep,2019,3145,APIO,size
来源: https://www.cnblogs.com/hchhch233/p/11096931.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有