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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

YbtOJ#883-最大的割【带修线性基】

發布時間:2023/12/3 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 YbtOJ#883-最大的割【带修线性基】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:http://www.ybtoj.com.cn/contest/118/problem/3


解題思路

給出nnn個點,mmm次動態插入一條無向邊詢問:割掉一些邊使得圖中至少兩點不連通,并且割掉的邊異或和最大。

詢問之間相互獨立

1≤n≤500,1≤m≤10001\leq n\leq 500,1\leq m\leq 10001n500,1m1000

邊權以二進制形式給出,長度不超過100010001000


解題思路

要求分隔兩個點,看起來很麻煩,其實有個結論。先定義wiw_iwi?表示連接iii的所有邊的異或和,如果選出了一個點集UUU和外面的所有點都隔絕,那么割就是點集UUU中所有點的wiw_iwi?值異或和。

其實挺顯然的,因為如果兩個點集中的點x,yx,yx,y之間的邊被異或了兩次就抵消掉了。

那么現在問題就變為了每次修改兩個數,求最大異或和。

然后就是帶修線性基的裸題了,有兩種方法

在線做法是先刪除再插入,就是開一個0行儲存所有的沒有成功插入線性基的元素,然后還要對于每個元素維護一個它插入的時候異或了哪些元素。

每次你刪除一個元素xxx的時候,假設集合SSS中儲存了所有插入的時候異或了xxx的元素(包括xxx本身),那么我們找出一個最小的y∈Sy\in SyS(異或后),讓所有SSS中的其他元素異或上yyy之后再將yxorcy\ xor\ cy?xor?c插入(ccc表示你要讓xxx異或的值)
此時就相當于你將之前插入xxx時本應該異或的數變成了異或xxorcx\ xor\ cx?xor?c的,選出最小的yyy防止對后面的元素產生影響,然后修改后讓yyy代替xxx成為新的主元插入。
加一個bitsetbitsetbitset優化,時間復雜度O(m(n+L)Lw)O(\frac{m(n+L)L}{w})O(wm(n+L)L?)

離線的做法是線段樹分治,一個xxx的取值會被分為不同的時間段,每次將xxx的固定的時間段插入到線段樹的對應區間,然后分治下去的時候維護一個撤銷線性基就好了。

時間復雜度O(mL2log?mw)O(\frac{mL^2\log m}{w})O(wmL2logm?)(也許?)

這里寫的是在線的做法


code

#include<cstdio> #include<cstring> #include<algorithm> #include<bitset> using namespace std; const int N=1010; bitset<N>w[N],v[N],c,ans; int n,m,p[N];char s[N]; void Insert(int x){for(int i=N-1;i>=0;i--)if(w[x][i]){if(p[i])w[x]^=w[p[i]],v[x]^=v[p[i]];else{p[i]=x;return;}}return; } void Change(int x){int pos=0;for(int i=1;i<=n;i++)if(v[i][x]&&!w[i].any()){pos=i;break;}if(!pos)for(int i=0;i<N;i++)if(p[i]&&v[p[i]][x]){pos=p[i];p[i]=0;break;}for(int i=1;i<=n;i++)if(v[i][x]&&i!=pos)w[i]^=w[pos],v[i]^=v[pos];w[pos]^=c;Insert(pos);return; } int main() {freopen("cut.in","r",stdin);freopen("cut.out","w",stdout);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)v[i][i]=1;for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);scanf("%s",s);int l=strlen(s);c.reset();for(int j=0;j<l;j++)c[j]=s[l-j-1]-'0';Change(x);Change(y);bool flag=0;ans.reset();for(int i=N-1;i>=0;i--){if(p[i]&&!ans[i])ans^=w[p[i]];if(ans[i])flag=1;if(flag)printf("%d",ans[i]?1:0);}if(!flag)puts("0");else putchar('\n');}return 0; }

總結

以上是生活随笔為你收集整理的YbtOJ#883-最大的割【带修线性基】的全部內容,希望文章能夠幫你解決所遇到的問題。

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