日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JZOJ 5466. 【NOIP2017提高A组冲刺11.9】玩游戏

發布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JZOJ 5466. 【NOIP2017提高A组冲刺11.9】玩游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

小A得了憂郁綜合癥,小B正在想辦法開導她。
機智的小B決定陪著小A玩游戲,他從魔法的世界里變出一張無向聯通圖,每條邊上都有邊權。小B定義一條路徑的權值為所有經過邊中的最大權值,小A則定義兩點的最短路徑為所有路徑中權值最小的路徑權。
每次小A和小B會選出k對點mi_1,mi_2,分別計算出mi_1,mi_2的最短路徑ti,然后小B會拿出k堆靈魂寶石,每堆有ti個。然后小A先從一堆中選出若干個靈魂寶石拿走,接下來小B重復同樣的操作,如此反復,直到取走最后一顆靈魂寶石,然后取走最后一顆寶石的人獲勝。
小B認為這樣游戲太簡單,于是他會不定期向這張圖上加上一些邊,以增大游戲難度。
小A具有預知未來的能力,她看到了自己和小B在未來游戲中的選擇,以及小B增加的邊。現在對于每次游戲,小A想知道自己是否存在必勝的方法。但是預知未來已經消耗了她太多精力,出于疲憊她只好找到了你。

Input

第一行三個數N和M和K,表示這張無向圖初始的點數與邊數,以及每次詢問的點對的個數;
接下來M行,每行三個數u,v,q,表示點u和點v之間存在一條權值為q的
邊;
接下來一行一個數Q,表示操作總數;
接下來Q行,表示操作,每行格式為下面兩條中的一條:
1.add u v q:表示在u與v之間加上一條邊權為q的邊;
2.game m1_1 m1_2 … mk_1 mk_2:表示一次游戲中選擇的k對點。
數據保證1≤u,v,mi_1,mi_2≤n,1≤q,mi_1≠mi_2

Output

對于每個game輸出一行,若小A存在必勝策略,則輸出“madoka”,否則輸出“Baozika”,以回車結尾

Sample Input

5 6 2
1 2 3
2 3 6
4 2 4
5 3 5
3 4 5
5 1 5
4
game 1 3 4 3
game 1 5 2 4
add 2 5 4
game 1 5 3 4

Sample Output

Baozika
madoka
madoka

Data Constraint

Solution

  • 首先考慮獲勝策略。k 堆石子,每堆石子數量為 ai

  • A 和 B 玩游戲,輪流從其中某一堆石子中取出若干個石子,最后取完石子的人獲勝。

  • 結論:如 a1?xor?a2?xor?...?xor?ak=0 ,則先手輸,否則先手贏,xor 表示異或。

  • 證明:若 a1?xor?a2?xor?...?xor?an0 ,則一定可以從其中某堆石子中取出一些石子,

  • 使得剩下的石子數異或結果為 0,若 a1?xor?a2?xor?...?xor?an=0

  • 則進行一次取石子操作后 a1?xor?a2?xor?...?xor?an 一定不等于 0,

  • 按照這樣的操作下去,最后一定會出現 a1=a2=?...?=an=0 的情況。

  • 問題就變成了加邊和求路徑長

算法1

  • 看到詢問次數很少,考慮 倍增+LCA

  • 根據最小生成樹的性質,我們發現路徑一定在 無向圖的最小生成樹 上。

  • 每次維護最小生成樹,完成詢問用樹上 LCA 即可。

  • 事實上,加入一條邊只有可能改變最小生成樹上的一條邊。

  • 假設加邊為 x,y,z,我們可以找到 xy 的路徑上的最大邊權。

  • 若該邊權 >z ,顯然將新邊加入更優,否則忽略新邊。

  • 再將所有邊用 O(N) 的插入排序排序即可。

  • 套上在線 LCA 算法就可以愉快的 AC 了。

  • 時間復雜度 O(D?NlogN+(Q?D)?logN) ,其中 D 為加邊次數。

  • 注意存邊權要開 long long

算法2

  • 如果加邊次數不限呢?直接上 LCT 啊!

  • Link?Cut?Tree 維護最小生成樹即可。

  • 若當前加入的邊小于當前樹中邊權的最大值,則將那個最大的邊刪去,再連當前邊。

  • 維護邊權的話可以開一個虛點存邊權,再連向兩個點即可。

  • 注意開夠數組范圍。

Code(倍增LCA)

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int N=5002,M=105001; struct data {int x,y;LL z; }a[M]; int tot,num; int first[N],next[N<<1],en[N<<1]; LL w[N<<1]; int f[N],size[N],fa[N][13],dep[N]; LL g[N][13]; template<typename T>inline T read() {T X=0,w=0; char ch=0;while(ch<'0' || ch>'9') {w|=ch=='-';ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline LL max(LL x,LL y) {return x>y?x:y; } inline bool cmp(data x,data y) {return x.z<y.z; } inline int get(int x) {return f[x]==x?x:f[x]=get(f[x]); } inline bool merge(int x,int y) {if(get(x)==get(y)) return false;if(size[f[x]]<size[f[y]]) swap(x,y);size[f[x]]+=size[f[y]];f[f[y]]=x;return true; } inline void insert(int x,int y,LL z) {next[++tot]=first[x];first[x]=tot;en[tot]=y;w[tot]=z; } inline void dfs(int x) {dep[x]=dep[fa[x][0]]+1;for(int i=first[x];i;i=next[i])if(en[i]^fa[x][0]){fa[en[i]][0]=x;g[en[i]][0]=w[i];dfs(en[i]);} } inline LL lca(int x,int y) {if(dep[x]<dep[y]) swap(x,y);LL mx=0;for(int i=log2(dep[x]);i>=0;i--)if(dep[fa[x][i]]>=dep[y]){mx=max(mx,g[x][i]);x=fa[x][i];}if(x==y) return mx;for(int i=log2(dep[x]);i>=0;i--)if(fa[x][i]!=fa[y][i]){mx=max(mx,max(g[x][i],g[y][i]));x=fa[x][i],y=fa[y][i];}mx=max(mx,max(g[x][0],g[y][0]));return mx; } int main() {int n=read<int>(),m=read<int>(),k=read<int>();for(int i=1;i<=m;i++)a[i].x=read<int>(),a[i].y=read<int>(),a[i].z=read<LL>();sort(a+1,a+1+m,cmp);for(int i=1;i<=n;i++) size[f[i]=i]=1;for(int i=1,k=1;i<=m;i++)if(merge(a[i].x,a[i].y)){insert(a[i].x,a[i].y,a[i].z);insert(a[i].y,a[i].x,a[i].z);a[++num]=a[i];if(++k==n) break;}dfs(1);for(int j=1,p=log2(n);j<=p;j++)for(int i=1;i<=n;i++){fa[i][j]=fa[fa[i][j-1]][j-1];g[i][j]=max(g[fa[i][j-1]][j-1],g[i][j-1]);}int q=read<int>();while(q--){char ch=getchar();while(ch!='g' && ch!='a') ch=getchar();if(ch=='g'){LL ans=0;for(int i=1;i<=k;i++) ans^=lca(read<int>(),read<int>());if(ans) puts("madoka"); else puts("Baozika");}else{int x=read<int>(),y=read<int>();LL z=read<LL>();if(lca(x,y)<=z) continue;tot=fa[1][0]=0;memset(first,0,sizeof(first));memset(g,0,sizeof(g));//a[++num]=(data){x,y,z};//sort(a+1,a+1+num,cmp);bool pd=true;for(int i=1;i<=num;i++)if(z<=a[i].z){for(int j=++num;j>i;j--) a[j]=a[j-1];a[i]=(data){x,y,z};pd=false;break;}if(pd) a[++num]=(data){x,y,z};for(int i=1;i<=n;i++) size[f[i]=i]=1;num=0;for(int i=1,k=1;i<=n;i++)if(merge(a[i].x,a[i].y)){insert(a[i].x,a[i].y,a[i].z);insert(a[i].y,a[i].x,a[i].z);a[++num]=a[i];if(++k==n) break;}dfs(1);for(int j=1,p=log2(n);j<=p;j++)for(int i=1;i<=n;i++){fa[i][j]=fa[fa[i][j-1]][j-1];g[i][j]=max(g[fa[i][j-1]][j-1],g[i][j-1]);}}}return 0; }

Code(Link-Cut-Tree)

#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; typedef long long LL; const int N=110005; struct data {int x,y; }a[N]; int tot,top; int fa[N],s[N][2],mx[N],st[N]; LL key[N]; bool rev[N]; template<typename T>inline T read() {T X=0,w=0; char ch=0;while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline bool pd(int x) {return x==s[fa[x]][1]; } inline bool isroot(int x) {return s[fa[x]][0]^x && s[fa[x]][1]^x; } inline void modify(int x) {if(x) swap(s[x][0],s[x][1]),rev[x]^=1; } inline void update(int x) {mx[x]=key[mx[s[x][0]]]>key[mx[s[x][1]]]?mx[s[x][0]]:mx[s[x][1]];if(key[x]>key[mx[x]]) mx[x]=x; } inline void down(int x) {if(rev[x]){modify(s[x][0]),modify(s[x][1]);rev[x]=false;} } inline void rotate(int x) {int y=fa[x],w=pd(x);if(s[y][w]=s[x][w^1]) fa[s[x][w^1]]=y;if((fa[x]=fa[y]) && !isroot(y)) s[fa[y]][pd(y)]=x;s[fa[y]=x][w^1]=y;update(y); } inline void splay(int x) {for(int y=st[top=1]=x;!isroot(y);y=fa[y]) st[++top]=fa[y];while(top) down(st[top--]);for(int y;!isroot(x);rotate(x))if(!isroot(y=fa[x])) rotate(pd(x)==pd(y)?y:x);update(x); } inline void access(int x) {for(int y=0;x;x=fa[y=x]) splay(x),s[x][1]=y,update(x); } inline void mkroot(int x) {access(x),splay(x),modify(x); } inline void link(int x,int y) {mkroot(x),fa[x]=y; } inline void cut(int x,int y) {mkroot(x),access(y),splay(y);fa[x]=s[y][0]=0; } inline int get(int x) {access(x),splay(x);int y=x;while(s[y][0]) y=s[y][0];return y; } int main() {int n=tot=read<int>(),m=read<int>(),k=read<int>();for(int i=1;i<=m;i++){int x=read<int>(),y=read<int>();LL z=read<LL>();a[i]=(data){x,y};key[mx[++tot]=tot]=z;if(get(x)^get(y)) link(tot,x),link(tot,y); else{mkroot(x),access(y),splay(y);int del=mx[y];if(z<key[del]){cut(del,a[del-n].x),cut(del,a[del-n].y);link(tot,x),link(tot,y);}}}int q=read<int>();while(q--){char ch=getchar();while(ch^'g' && ch^'d') ch=getchar();if(ch=='g'){LL ans=0;for(int i=1;i<=k;i++){int x=read<int>(),y=read<int>();mkroot(x),access(y),splay(y);ans^=key[mx[y]];}puts(ans?"madoka":"Baozika");}else{int x=read<int>(),y=read<int>();LL z=read<LL>();a[++m]=(data){x,y};key[mx[++tot]=tot]=z;if(get(x)^get(y)) link(tot,x),link(tot,y); else{mkroot(x),access(y),splay(y);int del=mx[y];if(z<key[del]){cut(del,a[del-n].x),cut(del,a[del-n].y);link(tot,x),link(tot,y);}}}}return 0; }

總結

以上是生活随笔為你收集整理的JZOJ 5466. 【NOIP2017提高A组冲刺11.9】玩游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。