「一本通 4.4 例 3」异象石 与 [SDOI2015]寻宝游戏
这两个题差不多先说异象石把
主要是找到本题规律,将所加入的点按dfs序排序,记录为a[1],a[2]..a[n]则当前的答案为每个点与前一个点的距离(第一个点则与最后一点)
当然要动态维护答案,每加入一个点就+与前驱的距离+与后驱的距离-前驱与后驱的距离(删点的话ans减去这个值就好
不过异象石最后的答案要/2;
至于维护的话用set就好
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn = 1e5+10; 5 int n,head[maxn],dfsn[maxn],id[maxn],size,dp[maxn][30],cnt=0,maxd,deep[maxn],k,m; 6 7 ll dis[maxn][30]; 8 9 set<int> s; 10 11 set<int> ::iterator it,qi,ho; 12 13 struct edge{ 14 int v,w,nex; 15 }e[maxn<<1]; 16 17 void adde(int u,int v,int w){ 18 e[size].v=v;e[size].w=w;e[size].nex=head[u];head[u]=size++; 19 } 20 21 void bfs(int u){ 22 queue<int> q;q.push(u); 23 while(!q.empty()){ 24 u=q.front();q.pop(); 25 if(dp[u][0]!=-1) maxd=max(maxd,deep[u]=deep[dp[u][0]]+1); 26 for(int i=head[u];~i;i=e[i].nex){ 27 int v=e[i].v;if(v==dp[u][0]) continue; 28 dp[v][0]=u;dis[v][0]=e[i].w; 29 q.push(v); 30 } 31 } 32 } 33 34 void doubling(){ 35 for(int j=1;j<=k;j++) 36 for(int i=1;i<=n;i++) 37 if(dp[i][j-1]!=-1) dp[i][j]=dp[dp[i][j-1]][j-1],dis[i][j]=dis[i][j-1]+dis[dp[i][j-1]][j-1]; 38 } 39 40 void dfs(int u){ 41 dfsn[++cnt]=u;id[u]=cnt; 42 for(int i=head[u];~i;i=e[i].nex){ 43 int v=e[i].v; 44 if(!id[v]) dfs(v); 45 } 46 } 47 48 char getc(){ 49 char ch=getchar();while(ch!='+'&&ch!='-'&&ch!='?') ch=getchar(); 50 return ch; 51 } 52 53 ll lca(int x,int y){ 54 ll ans=0; 55 if(deep[x]<deep[y]) swap(x,y); 56 for(int i=k;i>=0;i--) 57 if(dp[x][i]!=-1&&deep[dp[x][i]]>=deep[y]) ans+=dis[x][i],x=dp[x][i]; 58 if(x==y) return ans; 59 for(int i=k;i>=0;i--) 60 if(dp[x][i]!=dp[y][i]){ 61 ans+=dis[x][i]+dis[y][i]; 62 x=dp[x][i],y=dp[y][i]; 63 } 64 return ans+dis[x][0]+dis[y][0]; 65 } 66 67 int main(){ 68 //freopen("in.txt","r",stdin); 69 //freopen("out.txt","w",stdout); 70 scanf("%d",&n); 71 memset(head,-1,sizeof(head)); 72 memset(dp,-1,sizeof(dp)); 73 for(int i=1;i<n;i++){ 74 int u,v,w; 75 scanf("%d%d%d",&u,&v,&w); 76 adde(u,v,w);adde(v,u,w); 77 } 78 bfs(1); 79 k=(int) (log(maxd)/log(2)); 80 doubling(); 81 dfs(1); 82 ll ans=0;scanf("%d",&m); 83 while(m--){ 84 char a=getc();int u; 85 if(a=='+'){ 86 scanf("%d",&u); 87 if(s.empty()){ 88 s.insert(id[u]); 89 } 90 else { 91 s.insert(id[u]); 92 it=s.find(id[u]); 93 qi=it;if(qi==s.begin()) {qi=s.end();qi--;} 94 else qi--; 95 ho=it;ho++;if(ho==s.end()) ho=s.begin(); 96 ll aa=lca(dfsn[*qi],dfsn[*it]); 97 ll bb=lca(dfsn[*it],dfsn[*ho]); 98 ll cc=lca(dfsn[*qi],dfsn[*ho]); 99 ans+=aa+bb-cc; 100 } 101 } 102 else if(a=='-'){ 103 scanf("%d",&u); 104 it=s.find(id[u]); 105 qi=it;if(qi==s.begin()) {qi=s.end();qi--;} 106 else qi--; 107 ho=it;ho++;if(ho==s.end()) ho=s.begin(); 108 ll aa=lca(dfsn[*qi],dfsn[*it]); 109 ll bb=lca(dfsn[*it],dfsn[*ho]); 110 ll cc=lca(dfsn[*qi],dfsn[*ho]); 111 ans-=aa+bb-cc; 112 s.erase(id[u]); 113 } 114 else printf("%lld\n",ans/2); 115 } 116 return 0; 117 }
至于寻宝游戏就在输入时处理下就好,其他一样的(输出时不除二)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn = 1e5+10; 5 int n,head[maxn],dfsn[maxn],id[maxn],size,dp[maxn][30],cnt=0,maxd,deep[maxn],k,m,vis[maxn]; 6 7 ll dis[maxn][30]; 8 9 set<int> s; 10 11 set<int> ::iterator it,qi,ho; 12 13 struct edge{ 14 int v,w,nex; 15 }e[maxn<<1]; 16 17 void adde(int u,int v,int w){ 18 e[size].v=v;e[size].w=w;e[size].nex=head[u];head[u]=size++; 19 } 20 21 void bfs(int u){ 22 queue<int> q;q.push(u); 23 while(!q.empty()){ 24 u=q.front();q.pop(); 25 if(dp[u][0]!=-1) maxd=max(maxd,deep[u]=deep[dp[u][0]]+1); 26 for(int i=head[u];~i;i=e[i].nex){ 27 int v=e[i].v;if(v==dp[u][0]) continue; 28 dp[v][0]=u;dis[v][0]=e[i].w; 29 q.push(v); 30 } 31 } 32 } 33 34 void doubling(){ 35 for(int j=1;j<=k;j++) 36 for(int i=1;i<=n;i++) 37 if(dp[i][j-1]!=-1) dp[i][j]=dp[dp[i][j-1]][j-1],dis[i][j]=dis[i][j-1]+dis[dp[i][j-1]][j-1]; 38 } 39 40 void dfs(int u){ 41 dfsn[++cnt]=u;id[u]=cnt; 42 for(int i=head[u];~i;i=e[i].nex){ 43 int v=e[i].v; 44 if(!id[v]) dfs(v); 45 } 46 } 47 48 /*char getc(){ 49 char ch=getchar();while(ch!='+'&&ch!='-'&&ch!='?') ch=getchar(); 50 return ch; 51 }*/ 52 53 ll lca(int x,int y){ 54 ll ans=0; 55 if(deep[x]<deep[y]) swap(x,y); 56 for(int i=k;i>=0;i--) 57 if(dp[x][i]!=-1&&deep[dp[x][i]]>=deep[y]) ans+=dis[x][i],x=dp[x][i]; 58 if(x==y) return ans; 59 for(int i=k;i>=0;i--) 60 if(dp[x][i]!=dp[y][i]){ 61 ans+=dis[x][i]+dis[y][i]; 62 x=dp[x][i],y=dp[y][i]; 63 } 64 return ans+dis[x][0]+dis[y][0]; 65 } 66 67 int main(){ 68 //freopen("in.txt","r",stdin); 69 //freopen("out.txt","w",stdout); 70 scanf("%d",&n);scanf("%d",&m); 71 memset(head,-1,sizeof(head)); 72 memset(dp,-1,sizeof(dp)); 73 for(int i=1;i<n;i++){ 74 int u,v,w; 75 scanf("%d%d%d",&u,&v,&w); 76 adde(u,v,w);adde(v,u,w); 77 } 78 bfs(1); 79 k=(int) (log(maxd)/log(2)); 80 doubling(); 81 dfs(1); 82 ll ans=0; 83 while(m--){ 84 //char a=getc(); 85 int u;scanf("%d",&u); 86 if(!vis[u]){ 87 vis[u]=1; 88 if(s.empty()){ 89 s.insert(id[u]); 90 } 91 else { 92 s.insert(id[u]); 93 it=s.find(id[u]); 94 qi=it;if(qi==s.begin()) {qi=s.end();qi--;} 95 else qi--; 96 ho=it;ho++;if(ho==s.end()) ho=s.begin(); 97 ll aa=lca(dfsn[*qi],dfsn[*it]); 98 ll bb=lca(dfsn[*it],dfsn[*ho]); 99 ll cc=lca(dfsn[*qi],dfsn[*ho]); 100 ans+=aa+bb-cc; 101 } 102 } 103 else if(vis[u]){ 104 vis[u]=0; 105 it=s.find(id[u]); 106 qi=it;if(qi==s.begin()) {qi=s.end();qi--;} 107 else qi--; 108 ho=it;ho++;if(ho==s.end()) ho=s.begin(); 109 ll aa=lca(dfsn[*qi],dfsn[*it]); 110 ll bb=lca(dfsn[*it],dfsn[*ho]); 111 ll cc=lca(dfsn[*qi],dfsn[*ho]); 112 ans-=aa+bb-cc; 113 s.erase(id[u]); 114 } 115 printf("%lld\n",ans); 116 } 117 return 0; 118 }