zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    帝国 标签模板 使用程序代码 去除html标记 并 截取字符串
    iis6 伪静态 iis配置方法 【图解】
    您来自的链接不存在 帝国CMS
    帝国cms Warning: Cannot modify header information headers already sent by...错误【解决方法】
    .fr域名注册 51元注册.fr域名
    帝国网站管理系统 恢复栏目目录 建立目录不成功!请检查目录权限 Godaddy Windows 主机
    星外虚拟主机管理平台 开通数据库 出现Microsoft OLE DB Provider for SQL Server 错误 '8004' 从字符串向 datetime 转换失败
    ASP.NET 自定义控件学习研究
    CSS层叠样式表之CSS解析机制的优先级
    ASP.NET程序员工作面试网络收藏夹
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13833615.html
Copyright © 2011-2022 走看看