Codeforces 487E

传送门

题意:

给出一个无向联通图,求一个点不经过重复点可以到达点的最小权值,需要兹瓷修改权值。

先求点双连通分量,然后缩点,形成一棵树,每个新点的权值是其中所有点的最小权值。

然额,割点属于多个点双连通分量,每次直接修改会TLE(一棵菊花树就可以做到),

所以对每个点双新建一个结点,对属于它的点连边,这样每个原来的点的父亲一定是它所属的点双。

之后对每个点双建一个multiset维护最小值,查询时用树链剖分加线段树。

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <set>
  5 using namespace std;
  6 #define maxn 100001
  7 template<typename __>
  8 inline void read(__ &s)
  9 {
 10     char ch;
 11     for(ch=getchar(),s=0;ch<'0'||ch>'9';ch=getchar());
 12     for(;ch>='0'&&ch<='9';ch=getchar())
 13         s=s*10+ch-'0';
 14 }
 15 struct edge
 16 {
 17     int u,v,nex;
 18 }e[maxn<<1];
 19 int pr[maxn],cnt;
 20 void add(int u,int v)
 21 {
 22     e[++cnt]=(edge){u,v,pr[u]};
 23     pr[u]=cnt;
 24     e[++cnt]=(edge){v,u,pr[v]};
 25     pr[v]=cnt;
 26 }
 27 int n,m,bcc_cnt,bcc_dfn,top,q;
 28 int dfn[maxn],low[maxn],cut[maxn<<1];
 29 int s[maxn],belong[maxn<<1],st[maxn];
 30 multiset<int>mst[maxn];
 31 class seg
 32 {
 33 public:
 34     struct edge
 35     {
 36         int u,v,nex;
 37     }e[maxn<<2];
 38     int cnt,dfn,N;
 39     int siz[maxn<<1],depth[maxn<<1],top[maxn<<1],pr[maxn<<1];
 40     int son[maxn<<1],fa[maxn<<1],L[maxn<<1],quit[maxn<<1];
 41     bool vis[maxn<<1];
 42     multiset<int>::iterator it;
 43     void add(int u,int v)
 44     {
 45         e[++cnt]=(edge){u,v,pr[u]};
 46         pr[u]=cnt;
 47         e[++cnt]=(edge){v,u,pr[v]};
 48         pr[v]=cnt;
 49     }
 50     void dfs_make(int u)
 51     {
 52         int v;
 53         siz[u]=vis[u]=1;
 54         for(int i=pr[u];i;i=e[i].nex)
 55         {
 56             v=e[i].v;
 57             if(!vis[v])
 58             {
 59                 depth[v]=depth[u]+1;
 60                 fa[v]=u;
 61                 dfs_make(v);
 62                 siz[u]+=siz[v];
 63                 if(siz[v]>siz[son[u]])
 64                     son[u]=v;
 65             }
 66         }
 67     }
 68     void dfs_lines(int u,int f)
 69     {
 70         int v;
 71         vis[u]=1;
 72         L[u]=++dfn;
 73         quit[dfn]=u;
 74         top[u]=f;
 75         if(son[u])
 76             dfs_lines(son[u],f);
 77         for(int i=pr[u];i;i=e[i].nex)
 78         {
 79             v=e[i].v;
 80             if(!vis[v])
 81                 dfs_lines(v,v);
 82         }
 83     }
 84     struct node
 85     {
 86         int minn;
 87     }tree[maxn<<3];
 88     #define lson id<<1,l,mid
 89     #define rson id<<1|1,mid+1,r
 90     #define INF 0x7fffffff
 91     inline void pushup(int id)
 92     {
 93         tree[id].minn=min(tree[id<<1].minn,tree[id<<1|1].minn);
 94     }
 95     void build(int id,int l,int r)
 96     {
 97         if(l==r)
 98         {
 99             tree[id].minn=s[quit[l]];
100             return ;
101         }
102         int mid=(l+r)>>1;
103         build(lson);
104         build(rson);
105         pushup(id);
106     }
107     int query(int id,int l,int r,int L,int R)
108     {
109         if(L<=l&&r<=R)
110             return tree[id].minn;
111         int mid=(l+r)>>1;
112         if(R<=mid)
113             return query(lson,L,R);
114         else
115             if(L>mid)
116                 return query(rson,L,R);
117             else
118                 return min(query(lson,L,mid),query(rson,mid+1,R));
119     }
120     void update(int id,int l,int r,int pos,int val)
121     {
122         if(l==r)
123         {
124             tree[id].minn=val;
125             return ;
126         }
127         int mid=(l+r)>>1;
128         if(pos<=mid)
129             update(lson,pos,val);
130         else
131             update(rson,pos,val);
132         pushup(id);
133     }
134     int query(int u,int v)
135     {
136         int ans=INF;
137         while(top[u]!=top[v])
138         {
139             if(depth[top[u]]<depth[top[v]])
140                 swap(u,v);
141             ans=min(ans,query(1,1,N,L[top[u]],L[u]));
142             u=fa[top[u]];
143         }
144         if(depth[u]>depth[v])
145             swap(u,v);
146         ans=min(ans,query(1,1,N,L[u],L[v]));
147         if(u>n)
148             ans=min(ans,s[fa[u]]);
149         return ans;
150     }
151     void init()
152     {
153         N=bcc_cnt;
154         dfs_make(1);
155         memset(vis,0,sizeof(vis));
156         dfs_lines(1,1);
157         for(int i=1;i<=n;i++)
158             if(fa[i]>n)
159                 mst[fa[i]-n].insert(s[i]);
160         for(int i=n+1;i<=N;i++)
161         {
162             it=mst[i-n].begin();
163             s[i]=*it;
164         }
165         build(1,1,N);
166     }
167     void change(int pos,int val)
168     {
169         int p=fa[pos]-n;
170         if(p>0)
171         {
172             it=mst[p].find(s[pos]);
173             mst[p].erase(it);
174             mst[p].insert(val);
175             it=mst[p].begin();
176             s[fa[pos]]=(*it);
177             update(1,1,N,L[fa[pos]],s[fa[pos]]);
178         }
179         update(1,1,N,L[pos],val);
180         s[pos]=val;
181     }
182 }T;
183 int find_fa(int x)
184 {
185     if(belong[x]==x)
186         return x;
187     return belong[x]=find_fa(belong[x]);
188 }
189 void UN(int x,int y)
190 {
191     int xx=find_fa(x),yy=find_fa(y);
192     if(xx!=yy)
193         belong[xx]=yy;
194 }
195 void tarjan(int u,int f)
196 {
197     int num=0,k,v;
198     st[++top]=u;
199     dfn[u]=low[u]=++bcc_dfn;
200     for(int i=pr[u];i;i=e[i].nex)
201     {
202         v=e[i].v;
203         if(!dfn[v])
204         {
205             tarjan(v,u);
206             low[u]=min(low[u],low[v]);
207             if(low[v]>=dfn[u])
208             {
209                 cut[u]=1;
210                 ++bcc_cnt;
211                 do
212                 {
213                     k=st[top--];
214                     T.add(k,bcc_cnt);
215                     UN(bcc_cnt,k);
216                 }while(k!=v);
217                 T.add(u,bcc_cnt);
218                 UN(u,bcc_cnt);
219             }
220         }
221         else
222             if(v!=f)
223                 low[u]=min(low[u],dfn[v]);
224     }
225 }
226 int main()
227 {
228     read(n);
229     read(m);
230     read(q);
231     int u,v,i,j;
232     for(i=1;i<=n;i++)
233         read(s[i]);
234     for(i=1;i<=m;i++)
235     {
236         read(u);
237         read(v);
238         add(u,v);
239     }
240     bcc_cnt=n;
241     tarjan(1,0);
242     for(i=1;i<=n;i++)
243         if(cut[i])
244             for(j=pr[i];j;j=e[j].nex)
245                 if(cut[e[j].v]&&find_fa(i)!=find_fa(e[j].v))
246                 {
247                     ++bcc_cnt;
248                     T.add(i,bcc_cnt);
249                     T.add(e[j].v,bcc_cnt);
250                 }
251     T.init();
252     char op[2];
253     for(i=1;i<=q;i++)
254     {
255         scanf("%s",op);
256         read(u);
257         read(v);
258         if(op[0]=='A')
259             printf("%d\n",T.query(u,v));
260         else
261             T.change(u,v);
262     }
263 }
codeforces 487E

偏偏出现在最后的补充说明:

如果两个点的LCA是一个新建结点,那LCA的fa也是一个属于该点的割点,修改时也要修改。

posted @ 2017-10-19 06:26  avancent  阅读(239)  评论(0编辑  收藏  举报