2017.1.20【初中部 GDKOI】模拟赛B组 邻近(near) 题解

原题:

http://172.16.0.132/senior/#contest/show/1911/0

题目描述:

有这么一群人决定随便做点什么。他们逐渐站成了一排。
而现在我们想知道每个人加入队伍后整个局面的友善值。
为了简化,我们这么描述这个问题:有n个无聊的人,对于一条长为m(n<=m)的线段,这n个人依次站到自己的位置上,其中第i个人位于位置pi(1<=pi<=m)上,且他的无聊值为bi(0<=bi<2^31)。我们定义一个队伍的友善值为每对相邻的人的契合度之和。两个人的契合度定义为他们的无聊值的异或值。
我们要知道的是在每个人加入之后整个队伍的友善值。为了更方便确认你能够得到答案,输出每个人加入后整个队伍的友善值的异或和即可。

输入:

第1行:2个非负整数n,m,表示无聊的人数和线段的长度。
第2至n+1行:第i+1行2个整数表示第i个人的位置pi和无聊值bi。

输出:

输出一个整数表示每个人加入后队伍的友善值的异或和。

样例输入:

5 10
10 7
1 7
9 1
2 6
8 0

样例输出:

12

数据范围限制:

对于30%的数据,m,n<=1000
对于60%的数据,m,n<=100000
对于100%的数据,n<=1000000,m<=2000000,n<=m
并且对于任意i,j(1<=i

分析:

先求出最后这个数列的总值,用链表存储,再往回删点,最后求出每次删点后的异或和

实现:

var
        a,b:array[0..1000000,1..2] of longint;
        nt,lt,bz:array[0..2000001] of longint;
        n,m,i,x,y:longint; ans,sum:int64;
procedure kp(l,r:longint);
var
        i,j,mid:longint;
begin
        i:=l; j:=r; mid:=b[(l+r) div 2,1];
        repeat
                while b[i,1]<mid do inc(i); while b[j,1]>mid do dec(j);
                if i<=j then
                begin
                        b[0]:=b[i]; b[i]:=b[j]; b[j]:=b[0];
                        inc(i); dec(j);
                end;
        until i>j;
        if l<j then kp(l,j); if i<r then kp(i,r);
end;
begin
        readln(n,m);
        for i:=1 to n do read(a[i,1],a[i,2]);
        b:=a; kp(1,n);
        for i:=1 to n do
        begin
                if i<>1 then lt[b[i,1]]:=b[i-1,1]; 
                if i<>n then nt[b[i,1]]:=b[i+1,1];
                bz[b[i,1]]:=b[i,2];
        end;
        for i:=1 to n-1 do inc(ans,(b[i,2] xor b[i+1,2]));
        sum:=ans;
        for i:=n downto 2 do
        begin
                x:=lt[a[i,1]]; y:=nt[a[i,1]];
                if x<>0 then dec(sum,(a[i,2] xor bz[x]));
                if y<>0 then dec(sum,(a[i,2] xor bz[y]));
                if (x<>0)and(y<>0)then inc(sum,(bz[x] xor bz[y]));
                lt[y]:=x; nt[x]:=y; ans:=ans xor sum;
        end;
        writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值