Description
有這麼一羣人決定隨便做點什麼。他們逐漸站成了一排。
而現在我們想知道每個人加入隊伍後整個局面的友善值。
爲了簡化,我們這麼描述這個問題:有n個無聊的人,對於一條長爲m(n<=m)的線段,這n個人依次站到自己的位置上,其中第i個人位於位置pi(1<=pi<=m)上,且他的無聊值爲bi(0<=bi<2^31)。我們定義一個隊伍的友善值爲每對相鄰的人的契合度之和。兩個人的契合度定義爲他們的無聊值的異或值。
我們要知道的是在每個人加入之後整個隊伍的友善值。爲了更方便確認你能夠得到答案,輸出每個人加入後整個隊伍的友善值的異或和即可。
Input
第1行:2個非負整數n,m,表示無聊的人數和線段的長度。
第2至n+1行:第i+1行2個整數表示第i個人的位置pi和無聊值bi。
Output
輸出一個整數表示每個人加入後隊伍的友善值的異或和。
Data Constraint
對於30%的數據,m,n<=1000
對於60%的數據,m,n<=100000
對於100%的數據,n<=1000000,m<=2000000,n<=m
並且對於任意i,j(1<=i<j<=n),有pi>pj或pi<pj
Solution
由於沒有強制在線,我們可以倒着做一遍。
設sum表示所有數的異或和,並且記錄每一個點的左邊的點和右邊的點。那麼我們倒着搜,每搜到一個點時,用sum減去它與他左邊和右邊的異或值,再加上它左邊與右邊的異或值,每次用ans異或sum就行了。
Code
#include <cstdio>
#include <algorithm>
using namespace std;
struct nade
{
int p, b;
}a[1000007], c[1000007];
int n, m;
long long ans, sum;
int lt[2000007], nt[2000007], bz[2000007];
bool cmp(nade a, nade b)
{
return a.p < b.p;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++ i)
{
scanf("%d%d", &a[i].p, &a[i].b);
c[i].p = a[i].p;
c[i].b = a[i].b;
}
sort(c + 1, c + 1 + n, cmp);
for (int i = 1; i <= n; ++ i)
{
if (i != 1) lt[c[i].p] = c[i - 1].p;
if (i != n) nt[c[i].p] = c[i + 1].p;
bz[c[i].p] = c[i].b;
}
for (int i = 1; i < n; ++ i) ans += (c[i].b ^ c[i + 1].b);
sum = ans;
for (int i = n; i > 1; -- i)
{
int x = lt[a[i].p];
int y = nt[a[i].p];
if (x != 0) sum -= (a[i].b ^ bz[x]);
if (y != 0) sum -= (a[i].b ^ bz[y]);
if (x != 0 && y != 0) sum += (bz[x] ^ bz[y]);
lt[y] = x, nt[x] = y;
ans = ans ^ sum;
}
printf("%lld\n", ans);
return 0;
}