• [luogu5163]WD与地图


    将删边改为插边,如果是无向图直接线段树合并即可,考虑如何将有向边转换为无向边

    令$t_{i}$表示当插入到第$t_{i}$条边时恰好满足$x_{i}$与$y_{i}$在同一个强连通分量中,然后分类讨论:

    1.$t_{i}<i$或$t_{i}$不存在,这条边无意义,删去;

    2.$t_{i}ge i$,将所有这类边按照$t_{i}$排序,之后视作无向边进行操作即可

    考虑如何求出$t_{i}$,整体二分,对于当前区间$[l,r]$,问题即如何求出时间在$[1,mid]$中所有边所构成的强连通分量

    我们将$[1,mid]$中的边分为两类:1.答案(不等同于时间)小于$l$;2.答案在$[l,r]$中

    第一类边对图的贡献仅仅只是强连通分量,即第一类边构成的图恰好是若干个强连通分量(否则就答案就不会小于$l$),因此用按秩合并并查集来维护强连通分量(要支持撤销)

    第二类边的数量即当前询问区间,可以暴力加入再求tarjan(只能搜有新边的点,这样复杂度可以保证)

    假设$n,m,q$同阶,总复杂度为$o(nlog_{2}n)$(并查集的$log_{n}$应该与整体二分和线段树合并独立)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define ll long long
      5 #define mid (l+r>>1)
      6 struct ji{
      7     int t,x,y;
      8 }a[N<<1],e[N<<1],ee[N<<1];
      9 struct ji2{
     10     int nex,to;
     11 }edge[N<<1];
     12 vector<int>vv,v[N<<1];
     13 vector<pair<int,int> >re;
     14 map<int,int>mat[N];
     15 int V,E,n,m,q,p,x,y,head[N],vis[N],dfn[N],low[N],st[N],fa[N],sz[N],w[N],r[N],ls[N*100],rs[N*100],f[N*100];
     16 ll ans[N<<1],sum[N*100];
     17 bool cmp(ji x,ji y){
     18     return x.t<y.t;
     19 }
     20 int find(int k){
     21     if (k==fa[k])return k;
     22     return find(fa[k]);
     23 }
     24 void add(int x,int y){
     25     edge[E].nex=head[x];
     26     edge[E].to=y;
     27     head[x]=E++;
     28 }
     29 void merge1(int x,int y){
     30     x=find(x);
     31     y=find(y);
     32     if (x!=y){
     33         if (sz[x]>sz[y])swap(x,y);
     34         fa[x]=y;
     35         sz[y]+=sz[x];
     36         re.push_back(make_pair(x,y));
     37     }
     38 }
     39 void dfs(int k){
     40     vis[k]=1;
     41     dfn[k]=low[k]=++dfn[0];
     42     st[++st[0]]=k;
     43     for(int i=head[k];i!=-1;i=edge[i].nex)
     44         if (!dfn[edge[i].to]){
     45             dfs(edge[i].to);
     46             low[k]=min(low[k],low[edge[i].to]);
     47         }
     48         else
     49             if (vis[edge[i].to])low[k]=min(low[k],dfn[edge[i].to]);
     50     if (dfn[k]==low[k]){
     51         int las=st[st[0]--];
     52         vis[las]=0;
     53         while (las!=k){
     54             vis[st[st[0]]]=0;
     55             merge1(st[st[0]],las);
     56             las=st[st[0]--];
     57         }
     58     }
     59 }
     60 void dfs(int l,int r,int x,int y){
     61     if (x>y)return;
     62     if (l==r){
     63         for(int i=x;i<=y;i++)
     64             if ((l<q)||(find(e[i].x)==find(e[i].y)))v[q-l+1].push_back(mat[e[i].x][e[i].y]);
     65         return;
     66     }
     67     vv.clear();
     68     for(int i=x;i<=y;i++){
     69         if (e[i].t>mid)continue;
     70         int x=find(e[i].x),y=find(e[i].y);
     71         vv.push_back(x);
     72         if (x!=y){
     73             vv.push_back(y);
     74             add(x,y);
     75         }
     76     }
     77     int sre=re.size();
     78     for(int i=0;i<vv.size();i++)
     79         if (!dfn[vv[i]])dfs(vv[i]);
     80     E=dfn[0]=0;
     81     for(int i=0;i<vv.size();i++){
     82         head[vv[i]]=-1;
     83         dfn[vv[i]]=0;
     84     }
     85     vv.clear();
     86     for(int i=x;i<=y;i++)
     87         if ((e[i].t<=mid)&&(find(e[i].x)==find(e[i].y)))vv.push_back(i);
     88     for(int i=x,j=vv.size();i<x+vv.size();i++)
     89         if ((e[i].t>mid)||(find(e[i].x)!=find(e[i].y)))swap(e[i],e[vv[--j]]);
     90     int svv=vv.size();
     91     dfs(mid+1,r,x+svv,y);
     92     while (re.size()>sre){
     93         sz[re[re.size()-1].second]-=sz[re[re.size()-1].first];
     94         fa[re[re.size()-1].first]=re[re.size()-1].first;
     95         re.pop_back();
     96     }
     97     dfs(l,mid,x,x+svv-1);
     98 }
     99 void update(int &k,int l,int r,int x,int y){
    100     if (!x)return;
    101     if (!k)k=++V;
    102     f[k]+=y;
    103     sum[k]+=x*y;
    104     if (l==r)return;
    105     if (x<=mid)update(ls[k],l,mid,x,y);
    106     else update(rs[k],mid+1,r,x,y);
    107 }
    108 long long query(int k,int l,int r,int x){
    109     if (l==r)return min(x,f[k])*l;
    110     if (x<=f[rs[k]])return query(rs[k],mid+1,r,x);
    111     return sum[rs[k]]+query(ls[k],l,mid,x-f[rs[k]]);
    112 }
    113 int merge(int k1,int k2){
    114     if ((!k1)||(!k2))return k1+k2;
    115     if ((!ls[k1])&&(!rs[k1])){
    116         f[k1]+=f[k2];
    117         sum[k1]+=sum[k2];
    118         return k1;
    119     }
    120     ls[k1]=merge(ls[k1],ls[k2]);
    121     rs[k1]=merge(rs[k1],rs[k2]);
    122     f[k1]=f[ls[k1]]+f[rs[k1]];
    123     sum[k1]=sum[ls[k1]]+sum[rs[k1]];
    124     return k1;
    125 }
    126 void merge2(int x,int y){
    127     x=find(x);
    128     y=find(y);
    129     if (x!=y){
    130         if (sz[x]>sz[y])swap(x,y);
    131         fa[x]=y;
    132         sz[y]+=sz[x];
    133         r[y]=merge(r[x],r[y]);
    134     }
    135 }
    136 int main(){
    137     scanf("%d%d%d",&n,&m,&q);
    138     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    139     memset(head,-1,sizeof(head));
    140     for(int i=1;i<=m;i++){
    141         scanf("%d%d",&e[i].x,&e[i].y);
    142         e[i].t=1;//t表示插入的时间 
    143         mat[e[i].x][e[i].y]=i;
    144     }
    145     for(int i=1;i<=q;i++){
    146         scanf("%d%d%d",&p,&x,&y);
    147         if (p==1)e[mat[x][y]].t=q-i+1;
    148         if (p==2)w[x]+=y;
    149         a[i]=ji{p,x,y};
    150     }
    151     sort(e+1,e+m+1,cmp);
    152     memcpy(ee,e,sizeof(ee));
    153     for(int i=1;i<=m;i++)mat[e[i].x][e[i].y]=i;
    154     for(int i=1;i<=n;i++){
    155         fa[i]=i;
    156         sz[i]=1;
    157     }
    158     dfs(1,q,1,m);
    159     for(int i=1;i<=n;i++){
    160         fa[i]=i;
    161         sz[i]=1;
    162         update(r[i],0,1e9,w[i],1);
    163     }
    164     for(int i=m;i;i--){
    165         for(int j=0;j<v[i].size();j++)merge2(ee[v[i][j]].x,ee[v[i][j]].y);
    166         if (a[i].t==3)ans[++ans[0]]=query(r[find(a[i].x)],0,1e9,a[i].y);
    167         if (a[i].t==2){
    168             update(r[find(a[i].x)],0,1e9,w[a[i].x],-1);
    169             w[a[i].x]-=a[i].y;
    170             update(r[find(a[i].x)],0,1e9,w[a[i].x],1);
    171         }
    172     }
    173     for(int i=ans[0];i;i--)printf("%lld
    ",ans[i]);
    174 }
    View Code
  • 相关阅读:
    61个下拉菜单实例
    简单图片放大效果
    QQ,MSN,Skype在线客服代码
    codesmith自定义模板之实体层
    如何利用缓存提高ASP.NET网站速度
    10+Jquery Tooltip Plugins and Tutorial Collection
    10个ajax 上传插件
    ASP.NET 中 “返回上一页”,“上一步”的实现方法
    执行多条SQL语句,事务处理
    [Asp.Net+C#]Datagrid使用技巧四(怎样控制在一个单元格中放置多个操作按钮及删除数据)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13833615.html
Copyright © 2020-2023  润新知