HDOJ 5296 Annoying problem LCA+数据结构

来源:互联网 发布:小米手机全系列 知乎 编辑:程序博客网 时间:2024/04/28 03:18


dfs一遍得到每个节点的dfs序,对于要插入的节点x分两种情况考虑:

1,如果x可以在集合中的某些点之间,找到左边和右边距离x最近的两个点,即DFS序小于x的DFS序最大点,和大于x的DFS序最小的点......

2.如果x在集合中的点某一侧,则找距离x的dfs序最小和最大的点

将x插入这个集合最少要走的距离为 dist[x]-dist[LCA(left,x)]-dist[LCA(right,x)]+dist[LCA(left,right)]


删除同理

Annoying problem

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 334    Accepted Submission(s): 95


Problem Description
Coco has a tree, whose nodes are conveniently labeled by 1,2,…,n, which has n-1 edge,each edge has a weight. An existing set S is initially empty.
Now there are two kinds of operation:

1 x: If the node x is not in the set S, add node x to the set S
2 x: If the node x is in the set S,delete node x from the set S

Now there is a annoying problem: In order to select a set of edges from tree after each operation which makes any two nodes in set S connected. What is the minimum of the sum of the selected edges’ weight ?

 

Input
one integer number T is described in the first line represents the group number of testcases.( T<=10 ) 
For each test:
The first line has 2 integer number n,q(0<n,q<=100000) describe the number of nodes and the number of operations.
The following n-1 lines each line has 3 integer number u,v,w describe that between node u and node v has an edge weight w.(1<=u,v<=n,1<=w<=100)
The following q lines each line has 2 integer number x,y describe one operation.(x=1 or 2,1<=y<=n)


 

Output
Each testcase outputs a line of "Case #x:" , x starts from 1.
The next q line represents the answer to each operation.

 

Sample Input
16 51 2 21 5 25 6 22 4 22 3 21 51 31 41 22 5
 

Sample Output
Case #1:06884
 

Author
FZUACM
 

Source
2015 Multi-University Training Contest 1
 


/* ***********************************************Author        :CKbossCreated Time  :2015年07月21日 星期二 21时06分11秒File Name     :HDOJ5296.cpp************************************************ */#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <string>#include <cmath>#include <cstdlib>#include <vector>#include <queue>#include <set>#include <map>using namespace std;typedef long long int LL;const int maxn=120100;const int INF=0x3f3f3f3f;struct Edge{int to,next,cost;}edge[maxn*2];int Adj[maxn],Size;void init() { memset(Adj,-1,sizeof(Adj)); Size=0; }void Add_Edge(int u,int v,int c){edge[Size].to=v; edge[Size].cost=c;edge[Size].next=Adj[u];Adj[u]=Size++;}int n,q;int dist[maxn],ti[maxn],cnt;void dfs(int len,int u,int fa){dist[u]=len; ti[u]=cnt;for(int i=Adj[u];~i;i=edge[i].next){int to=edge[i].to;int cost=edge[i].cost;if(to==fa) continue;cnt++;dfs(len+cost,to,u);}}/********************** LCA **********************************/const int DEG=20;int fa[maxn][DEG];int deg[maxn];void BFS(int root){queue<int> q;memset(deg,0,sizeof(deg));memset(fa,0,sizeof(fa));deg[root]=0;fa[root][0]=root;q.push(root);while(!q.empty()){int u=q.front(); q.pop();for(int i=1;i<DEG;i++){fa[u][i]=fa[fa[u][i-1]][i-1];}for(int i=Adj[u];~i;i=edge[i].next){int v=edge[i].to;if(v==fa[u][0]) continue;deg[v]=deg[u]+1;fa[v][0]=u;q.push(v);}}}int LCA(int u,int v){if(deg[u]>deg[v]) swap(u,v);int hu=deg[u],hv=deg[v];int tu=u,tv=v;for(int det=hv-hu,i=0;det;i++,det=det/2){if(det&1) tv=fa[tv][i];}if(tu==tv) return tu;for(int i=DEG-1;i>=0;i--){if(fa[tu][i]==fa[tv][i]) continue;tu=fa[tu][i]; tv=fa[tv][i];}return fa[tu][0];}struct Node{int val,cnt;bool operator<(const Node& nd) const { return cnt<nd.cnt; }bool operator==(const Node& nd) const { return val==nd.val; }bool operator!=(const Node& nd) const { return val!=nd.val; }};set<Node> st;int CL(int flag,Node ND){if(flag==0) st.erase(ND);set<Node>::iterator it1,it2;int x=ND.val;it2=st.upper_bound(ND);it1=it2; it1--;/// check if in midif(it1->val!=0&&it2->val!=n+10) /// in mid{int left=it1->val;int right=it2->val;if(flag) st.insert(ND);return dist[x]-dist[LCA(x,left)]-dist[LCA(x,right)]+dist[LCA(left,right)];}else // in side{if(it2->val==n+10) /// all in left{it2=st.begin(); it2++;int left=it2->val;int right=it1->val;if(flag) st.insert(ND);return dist[x]-dist[LCA(x,left)]-dist[LCA(x,right)]+dist[LCA(left,right)];}else if(it1->val==0) /// all in right{int left=it2->val;it1=st.end();it1--; it1--;int right=it1->val;if(flag) st.insert(ND);return dist[x]-dist[LCA(x,left)]-dist[LCA(x,right)]+dist[LCA(left,right)];}}}/// return change val of solveint solve(int kind,int x){Node ND = (Node){x,ti[x]};/// if in mid find nearst pointset<Node>::iterator it1,it2;if(kind==1) // add{if(st.count(ND)==1) return 0;if(st.size()==2){st.insert(ND);return 0;}else if(st.size()==3){it1=st.begin(); it1++;int v=it1->val;st.insert(ND);return dist[x]+dist[v]-2*dist[LCA(v,x)];}else{return CL(1,ND);}}else if(kind==2) // remove{if(st.count(ND)==0) return 0;if(st.size()==3){st.erase(ND);return 0;}else if(st.size()==4){it1=st.begin();it1++;int v=it1->val; it1++;int u=it1->val;st.erase(ND);return dist[u]+dist[v]-2*dist[LCA(u,v)];}else{return CL(0,ND);}}}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);int T_T,cas=1;scanf("%d",&T_T);while(T_T--){scanf("%d%d",&n,&q);init();for(int i=0,u,v,c;i<n-1;i++){scanf("%d%d%d",&u,&v,&c);Add_Edge(u,v,c); Add_Edge(v,u,c);}cnt=1; st.clear();st.insert((Node){0,-INF});st.insert((Node){n+10,INF});dfs(0,1,1); BFS(1);int all=0;printf("Case #%d:\n",cas++);while(q--){int k,x;scanf("%d%d",&k,&x);if(k==1) all+=solve(k,x);else if(k==2) all-=solve(k,x);printf("%d\n",all);}}        return 0;}



1 0