原題:
huyichen和xuzhenyi在玩乙個遊戲:他寫乙個由0和1組成的序列。 huyichen選其中的一段(比如第3位到第5位),問他這段裡面有奇數個1 還是偶數個1。xuzhenyi回答你的問題,然後huyichen繼續問。 xuzhenyi有可能在撒謊。huyichen要檢查xuzhenyi的答案,指出在xuzhenyi的第幾個回答一定有問題。 有問題的意思就是存在乙個01序列滿足這個回答前的所有回答,而且不存在序列 滿足這個回答前的所有回答及這個回答。
第1行乙個整數,是這個01序列的長度(
≤1000000000
)'>(≤1000000000)
(≤1000000000) 第2行乙個整數,是問題和答案的個數(
≤5000
)'>(≤5000)
(≤5000)。 第3行開始是問題和答案, 每行先有兩個整數,表示你詢問的段的開始位置和結束位置。 然後是xuzhenyi的回答。odd表示有奇數個1,even表示有偶數個
輸出一行,乙個數x,表示存在乙個01序列滿足第1到第x個回答, 但是不存在序列滿足第1到第x+1個回答。如果所有回答都沒問題,你就輸出 所有回答的個數。
很明顯,這道題是並查集(不要問我怎麼看出來的)。
由於資料太大,需要離散化。
所謂離散化,就是把較大的一組數進行排序,然後對他們根據大小重新賦值,當數的大小不對資料本身有影響,只有大小對其有影響時,可以使用離散化。
離散化的標準姿勢見 點這裡
然而蒟蒻並不會標準姿勢,說說自己的方法:
以本題為例,把所有的資料都存在nd結構體中
voidinit()
else
}}
讀進來之後進行離散化。
voiddiscretization()
else
if(nd[i+1].p!=nd[i].p)
}for(int i = 1;i<=m;i++)
}
這樣就離散完了。
接下來就是帶權並查集的操作。
在合併和路徑壓縮的時候處理。
思路就是將乙個區間右面的點認左面的點為父親,兩端區間合併的時候,根據奇偶性判斷,0表示偶數,1表示奇數(有點懶,具體0或1見**)。
int find(intx)
int fx =find(f[x]);
g[x] = (g[f[x]]+g[x])%2
;
return f[x] =fx;
}
最後上總**:
#include#include#include
#define ll long long
#define n 105550
using
namespace
std;
char c[20
];ll n;
intm;
int cnt = 1
;struct
node
nd[n+n+n];
intf[n];
intg[n];
intcmp(node a,node b)
void
init()
else
}}void
discretization()
else
if(nd[i+1].p!=nd[i].p)
}for(int i = 1;i<=m;i++)
}int find(int
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) find(y);
find(x);
}else
}void
solve()
for(int i = 1;i<=m;i++)
}printf(
"%d\n
",m);
}int
main()
包小胖的自傳
我,包小胖,乙個微胖的小胖子。首先糾正我的名字,我不姓包,但是為什麼我用包這個字,是因為 因為我離開家鄉之後,在遠離家鄉的地方找了第乙份工作以後的代號,包子。為什麼叫包子,因為我胖。為什麼叫小胖,因為相對來說,公司有比我更胖的。我喜歡刨根問底,喜歡走神,所以我興趣廣泛,從街舞到武術,再到結他,再到花...
vijos 1111 小胖的水果 lcs
xuzhenyi到大同水果店去買水果,但老闆huyichen告訴他每次只能買一種,但是xuzhenyi想吃兩種,於是在討價還價之後,huyichen說只要xuzhenyi能把他想要的兩種水果合併成一種,就能成功。你能幫他嗎?輸入檔案包含兩個要組合的水果名字。所有的名字最多有100個字母。有若干行 對...
小胖的疑惑 整數劃分 區間DP
小胖同學 同學是數學優等生,在高中乙個年段中數學總是考第一,楓少同學作為萬年老二 想要超過他,於是楓同學出了道難題給absolute error同學,並且跟他約定了如果absolute error做的出來他就轉學。這題大概是這樣,將整數t分成n份,每份裡面必須有數不能空,且不能有相同的分法 不考慮順...