HDU 6200 2017沈阳网络赛 树上区间更新,求和
Posted Lsxxxxxxxxxxxxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6200 2017沈阳网络赛 树上区间更新,求和相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6200
题意:给个图,有2种操作,一种是加一条无向边,二是查询u,v之间必须有的边的条数,所谓必须有的边就是对于u,v必须通过这条边才能到达。
解法:一个很简单的想法,搞出图上的一颗树,然后剩下的边当成询问点队加到更新点集,每加入一个更新点对,直接把u,v区间的值置为0即可,查询就直接区间求和,可以直接树剖来维护,简单暴力,读入挂卡过。还有1个log的做法,可以用LCT维护(这个没写,口胡的)
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5+5; typedef long long LL; struct edge{ int to,next; edge(){} edge(int to,int next):to(to),next(next){} }E[maxn*2]; struct FastIO { static const int S = 1310720; int wpos; char wbuf[S]; FastIO() : wpos(0) {} inline int xchar() { static char buf[S]; static int len = 0, pos = 0; if (pos == len) pos = 0, len = fread(buf, 1, S, stdin); if (pos == len) return -1; return buf[pos ++]; } inline int xuint() { int c = xchar(), x = 0; while (c <= 32) c = xchar(); for (; ‘0‘ <= c && c <= ‘9‘; c = xchar()) x = x * 10 + c - ‘0‘; return x; } inline int xint() { int s = 1, c = xchar(), x = 0; while (c <= 32) c = xchar(); if (c == ‘-‘) s = -1, c = xchar(); for (; ‘0‘ <= c && c <= ‘9‘; c = xchar()) x = x * 10 + c - ‘0‘; return x * s; } inline void xstring(char *s) { int c = xchar(); while (c <= 32) c = xchar(); for (; c > 32; c = xchar()) * s++ = c; *s = 0; } inline void wchar(int x) { if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0; wbuf[wpos ++] = x; } inline void wint(LL x) { if (x < 0) wchar(‘-‘), x = -x; char s[24]; int n = 0; while (x || !n) s[n ++] = ‘0‘ + x % 10, x /= 10; while (n--) wchar(s[n]); } inline void wstring(const char *s) { while (*s) wchar(*s++); } ~FastIO() { if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; } } io; int n, m, head[maxn],edgecnt, tim; int sz[maxn], top[maxn], son[maxn], dep[maxn]; int fa[maxn],tid[maxn]; void init(){ memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); edgecnt=tim=0; } void add(int u,int v){ E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++; } void dfs1(int u, int father, int d){ dep[u]=d; fa[u]=father; sz[u]=1; for(int i=head[u]; i+1; i=E[i].next){ int v=E[i].to; if(v!=father){ dfs1(v,u,d+1); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v; } } } void dfs2(int u, int tp){ top[u]=tp; tid[u]=++tim; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=head[u];i+1;i=E[i].next){ int v=E[i].to; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } } namespace DSU{ int fa1[maxn]; void init1(){ for(int i=1; i<maxn; i++) fa1[i]=i; } int find_set(int x){ if(x==fa1[x]) return x; else return fa1[x] = find_set(fa1[x]); } bool union_set(int x, int y){ x = find_set(x); y = find_set(y); if(x!=y){ fa1[x]=y; return 1; } else{ return 0; } } } using namespace DSU; namespace SegmentTree{ int sum[maxn<<2], lazy[maxn<<2]; void pushup(int rt){ sum[rt]=sum[rt*2]+sum[rt*2+1]; } void pushdown(int rt){ if(lazy[rt]){ lazy[rt*2]=lazy[rt]; lazy[rt*2+1]=lazy[rt]; sum[rt*2]=sum[rt*2+1]=0; lazy[rt]=0; } } void build(int l, int r, int rt){ lazy[rt] = 0; if(l == r){ sum[rt] = l!=1; return; } int mid = (l+r)/2; build(l,mid,rt*2); build(mid+1,r,rt*2+1); pushup(rt); } void update(int L, int R, int l, int r, int rt){ if(L<=l&&r<=R){ lazy[rt]=1; sum[rt]=0; return; } pushdown(rt); int mid=(l+r)/2; if(L<=mid) update(L,R,l,mid,rt*2); if(mid<R) update(L,R,mid+1,r,rt*2+1); pushup(rt); } int query(int L, int R, int l, int r, int rt){ if(L<=l&&r<=R) return sum[rt]; int mid=(l+r)/2; pushdown(rt); int ret=0; if(L<=mid) ret+=query(L,R,l,mid,rt*2); if(mid<R) ret+=query(L,R,mid+1,r,rt*2+1); return ret; } void update(int u, int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) swap(u,v); update(tid[top[u]], tid[u], 1, tim, 1); u = fa[top[u]]; } if(u == v) return; if(dep[u]<dep[v]) swap(u,v); update(tid[v]+1,tid[u],1,tim,1); } int query(int u, int v){ int ret=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) swap(u,v); ret += query(tid[top[u]], tid[u], 1, tim, 1); u = fa[top[u]]; } if(u==v) return ret; if(dep[u]<dep[v]) swap(u,v); ret += query(tid[v]+1,tid[u],1,tim,1); return ret; } } using namespace SegmentTree; int main() { int T,q,ks=0; T = io.xint(); while(T--){ printf("Case #%d:\n", ++ks); n = io.xint(); m = io.xint(); init(); init1(); vector <pair<int, int> > G; for(int i=1; i<=m; i++){ int u, v; u = io.xint(); v = io.xint(); if(union_set(u,v)){ add(u, v); add(v, u); }else{ G.emplace_back(u, v); } } dfs1(1,0,0); dfs2(1,1); build(1,n,1); for(auto &it:G){ update(it.first,it.second); } q = io.xint(); for(int i=1; i<=q; i++){ int op,x,y; op = io.xint(); x = io.xint(); y = io.xint(); if(op==1) update(x, y); else{ printf("%d\n", query(x,y)); } } } return 0; }
以上是关于HDU 6200 2017沈阳网络赛 树上区间更新,求和的主要内容,如果未能解决你的问题,请参考以下文章
2016 年沈阳网络赛---QSC and Master(区间DP)