「一本通 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 }

原文地址:https://www.cnblogs.com/plysc/p/10496458.html

时间: 2024-08-29 22:02:07

「一本通 4.4 例 3」异象石 与 [SDOI2015]寻宝游戏的相关文章

10249「一本通 1.3 例 5」weight

#10249「一本通 1.3 例 5」weight 题目描述 原题来自:USACO 已知原数列a1,a2,...,an中的前1项,前2项,前3项,... ,前 n 项的和,以及后 1 项,后 2 项,后 3 项,...,后 n 项的和,但是==所有的数都被打乱了顺序==.此外,我们还知道数列中的数存在于集合 S 中.试求原数列.当存在多组可能的数列时,求字典序最小的数列. 输入格式 第 1 行,一个整数 n . 第 2 行, 2 × n 个整数,注意:数据已被打乱. 第 3 行,一个整数 m ,

一本通1554【例 3】异象石

1554:[例 3]异象石 时间限制: 1000 ms         内存限制: 524288 KB 题目描述 原题来自:Contest Hunter Round #56 在 Adera 的异时空中有一张地图.这张地图上有 N 个点,有 N?1 条双向边把它们连通起来.起初地图上没有任何异象石,在接下来的 M 个时刻中,每个时刻会发生以下三种类型的事件之一: 地图的某个点上出现了异象石(已经出现的不会再次出现): 地图某个点上的异象石被摧毁(不会摧毁没有异象石的点): 向玩家询问使所有异象石所

「一本通 4.2 例 2」最敏捷的机器人(loj10120)

题目描述 Wind 设计了很多机器人.但是它们都认为自己是最强的,于是,一场比赛开始了-- 机器人们都想知道谁是最敏捷的,于是它们进行了如下一个比赛.首先,他们面前会有一排共 n 个数,它们比赛看谁能最先把每连续 k 个数中最大和最小值写下来,当然,这些机器人运算速度都很快,它们比赛的是谁写得快. 但是 Wind 也想知道答案,你能帮助他吗? 输入格式 第一行为 n,k,意义如题目描述. 第二行共 n 个数,为数字序列,所有数字均在 Pascal 的 longint 范围内,即所有数均为整数,且

「一本通 5.2 例 5」皇宫看守

题目描述 太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫. 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见.大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同. 可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫. 帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少. 输入格式 输入中数据描述一棵树,描述如下: 第一行 ,表示树中结点的数目. 第二行至第 行,每行描述每个宫殿结点信息,依次

#10114 「一本通 4.1 例 2」数星星 Stars

1536:[例 2]数星星 Stars 时间限制: 256 ms         内存限制: 65536 KB提交数: 630     通过数: 282 [题目描述] 原题来自:Ural 1028 天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标.如果一个星星的左下方(包含正左和正下)有 kk 颗星星,就说这颗星星是 kk 级的. 例如,上图中星星 55 是 33 级的(1,2,41,2,4 在它左下),星星 2,42,4 是 11 级的.例图中有 11 个 00 级,22 个 11 

#10115 「一本通 4.1 例 3」校门外的树

1537:[例 3]校门外的树 时间限制: 1000 ms         内存限制: 524288 KB提交数: 497     通过数: 216 [题目描述] 原题来自:Vijos P1448 校门外有很多树,学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两种操作: K=1K=1,读入 l,rl,r 表示在 ll 到 rr 之间种上一种树,每次操作种的树的种类都不同: K=2K=2,读入 l,rl,r 表示询问 ll 到 rr 之间有多少种树. 注意:每个位

#10034.「一本通 2.1 例 2」图书管理-哈希(双哈希思想)+邻接表

样例 样例输入 4 add Inside C# find Effective Java add Effective Java find Effective Java 样例输出 no yes 数据范围与提示 n<=30000 1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<string.h> 5 using namespace std; 6 typedef

loj10143. 「一本通 4.6 例 1」营业额统计

思路: 使用treap在线存数据,每次取出新读入数据的前驱与后继,与该数据差值较小的就是.(注意若已有同一个数据,特判ans+=0) #include<cstdio> #include<iostream> #include<cstdlib> #include<cmath> using namespace std; const int maxn = 100010; inline void qread(int &x) { x = 0; register

loj10147. 「一本通 5.1 例 1」石子合并

思路: 经典的区间dp,题解到处都是... #include<cstdio> #include<iostream> #include<cstdio> using namespace std; const int maxn = 1010; inline void qread(int &x){ x = 0; register int ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); w