JZOJ3882 [NOIP2014模擬] 鄰近(near)

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章