小胖的奇偶(Viojs1112)題解

原題:node

題目描述

   huyichen和xuzhenyi在玩一個遊戲:他寫一個由0和1組成的序列。 huyichen選其中的一段(好比第3位到第5位),問他這段裏面有奇數個1 仍是偶數個1。xuzhenyi回答你的問題,而後huyichen繼續問。 xuzhenyi有可能在撒謊。huyichen要檢查xuzhenyi的答案,指出在xuzhenyi的第幾個回答必定有問題。 有問題的意思就是存在一個01序列知足這個回答前的全部回答,並且不存在序列 知足這個回答前的全部回答及這個回答。數組

輸入格式

第1行一個整數,是這個01序列的長度1000000000)(≤1000000000) 第2行一個整數,是問題和答案的個數(5000)(≤5000)。 第3行開始是問題和答案, 每行先有兩個整數,表示你詢問的段的開始位置和結束位置。 而後是xuzhenyi的回答。odd表示有奇數個1,even表示有偶數個ui

輸出格式

輸出一行,一個數X,表示存在一個01序列知足第1到第X個回答, 可是不存在序列知足第1到第X+1個回答。若是全部回答都沒問題,你就輸出 全部回答的個數。atom


很明顯,這道題是並查集(不要問我怎麼看出來的)。spa

因爲數據太大,須要離散化。.net

所謂離散化,就是把較大的一組數進行排序,而後對他們根據大小從新賦值,當數的大小不對數據自己有影響,只有大小對其有影響時,可使用離散化。code

離散化的標準姿式見 點這裏xml

然而蒟蒻並不會標準姿式,說說本身的方法:blog

以本題爲例,把全部的數據都存在nd結構體中排序

void init() { for(int i = 1;i<=m;i++) { int x,y; scanf("%d%d%s",&x,&y,c); nd[i].p = x;//數組開三倍,p表示臨時變量。一倍存左端點。 nd[i+m].p = y;//二倍存右端點。 nd[i].num = i;//每一倍都要給他們打上編號,一會排序時後會亂。 nd[i+m].num = i;if(c[0]=='e') { nd[i+m+m].odd = 0;//三倍存奇偶 }else { nd[i+m+m].odd = 1; } } }

讀進來以後進行離散化。

void discretization() { for(int i = 1;i<=2*m;i++) { if(nd[nd[i].num].l==-1) { nd[nd[i].num].l = cnt-1; }else { nd[nd[i].num].r = cnt; } if(nd[i+1].p!=nd[i].p) { cnt++; //去重,不同的時候再+1 } } for(int i = 1;i<=m;i++) { nd[i].odd = nd[i+m+m].odd;從三倍搬回原數組 } }

這樣就離散完了。

接下來就是帶權並查集的操做。

在合併和路徑壓縮的時候處理。

思路就是將一個區間右面的點認左面的點爲父親,兩端區間合併的時候,根據奇偶性判斷,0表示偶數,1表示奇數(有點懶,具體0或1見代碼)。

int find(int x) { if(f[x]==x) { return f[x]; } int fx = find(f[x]); g[x] = (g[f[x]]+g[x])%2; return f[x] = fx; }

最後上總代碼:

#include<cstdio> #include<algorithm> #include<cmath>
#define ll long long
#define N 105550
using namespace std; char c[20]; ll n; int m; int cnt = 1; struct node { int l; int r; int num; int odd; int p; }nd[N+N+N]; int f[N]; int g[N]; int cmp(node a,node b) { return a.p < b.p; } void init() { for(int i = 1;i<=m;i++) { int x,y; scanf("%d%d%s",&x,&y,c); nd[i].p = x; nd[i+m].p = y; nd[i].num = i; nd[i+m].num = i; nd[i].l = -1; nd[i+m].l = -1; if(c[0]=='e') { nd[i+m+m].odd = 0; }else { nd[i+m+m].odd = 1; } } } void discretization() { for(int i = 1;i<=2*m;i++) { if(nd[nd[i].num].l==-1) { nd[nd[i].num].l = cnt-1; }else { nd[nd[i].num].r = cnt; } if(nd[i+1].p!=nd[i].p) { cnt++; } } for(int i = 1;i<=m;i++) { nd[i].odd = nd[i+m+m].odd; } } int find(int x) { if(f[x]==x) { return f[x]; } int fx = find(f[x]); g[x] = (g[f[x]]+g[x])%2; return f[x] = fx; } int ans; bool flag; void uion(int x,int y,int i) { int fx = find(x); int fy = find(y); if(fx==fy) { if((nd[i].odd==1&&g[x]==g[y])||(nd[i].odd==0&&g[x]!=g[y])) { ans = i-1; flag = 1; return ; } find(y); find(x); }else { f[fy] = fx; g[fy] = (g[x]+g[y]+nd[i].odd)%2; find(x); find(y); } } void solve() { for(int i = 1;i<=cnt;i++) { f[i] = i; } for(int i = 1;i<=m;i++) { int l = nd[i].l; int r = nd[i].r; uion(l,r,i); if(flag==1) { printf("%d\n",ans); return ; } } printf("%d\n",m); } int main() { scanf("%lld",&n); scanf("%d",&m); init(); sort(nd+1,nd+1+m+m,cmp); discretization(); solve(); return 0; }
相關文章
相關標籤/搜索