Description
你需要写一个数据结构,支持:
在x号元素后面插入一个新的元素,如果当前序列中有n个元素,那么新的元素的编号就是n。
询问两个元素x,y的在序列中的先后顺序。
初始时序列中只有1个元素,编号为0。
Input
第一行两个数type,m。type表示是否强制在线,如果强制在线,则type=1,否则type=0。m表示操作和询问的总数量。
对于询问,你需要维护一个答案ans,如果第i 次操作是询问,并且有x在序列中在y后面,则你需要令ans=ans^i,即用
ans^i更新ans的值;如果x在y前面或者x=y,则不需要改变ans的值。
接下来m行,每行第一个数是opt。opt=0表示这是一次插入操作,接下来读入一个数x,表示在x后面插入一个新元素;
pt=1则表示这是一次询问操作,接下来读入两个数x,y表示询问x与y的大小关系(如果是强制在线的话,插入操作读入
的是x',真正的x=(x'+ans)%n,询问操作读入的是x',y',真正的x=(x'+ans)%n,y=(y'+ans)%n,如果在序列中y在x前面,则你
需要将ans^i作为新的ans。
Output
一行一个非负整数,表示最终答案ans。
Sample Input 1
0 6 0 0 0 0 1 2 0 0 1 1 1 2 1 1 3
Sample Output 1
6
Sample Input 2
1 10 1 0 0 0 0 1 1 0 1 0 1 0 0 1 0 1 1 1 2 0 0 1 2 3 1 2 1
Sample Output 2
9
Hint
样例解释 :
初始序列是0.
第一次操作后,序列是0 1
第二次操作后,序列是0 2 1
第三次询问,2在0后面,所以答案要异或3.
第四次操作后,序列是0 2 1 3
第五次询问,1在2后面,所以答案要异或5.
第六次询问,1在3前面,所以答案不变。
那么最终答案就是3^5=6.
数据范围 :
保证x,y,x’,y’随机,且保证0≤x,y,x’,y’<当前序列中元素个数。
我用的数组模拟链表加上标号法。。。对于初始节点赋一个特别大的值,对于插入一个值,取两边标号的中位数
所以插入的时间复杂度为O(1),查询复杂度也为O(1);
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct nd{unsigned long long c,l;}tr[1000001];
unsigned long long n,k,ans,t=1;
unsigned long long num[10000000];
void insert(long long pos){
int temp=tr[pos].l;
num[t]=(num[pos]+num[tr[pos].l])/2;
tr[pos].l=t;tr[t].c=t;
tr[t].l=temp;
t+=1;
}
void check(long long b,long long c,int i)
{
if(num[b]<num[c])
ans=ans^i;
}
int main()
{
tr[0].l=9999999;
num[0]=9187201950435737471;
cin>>k>>n;
for(int i=1;i<=n;++i){
long long a,b,c;cin>>a>>b;
if(a==0 and k==0){insert(b);}
if(a==1 and k==0){cin>>c;check(b,c,i);}
if(a==0 and k==1){b=(b+ans)%t;insert(b);}
if(a==1 and k==1){cin>>c;c=(c+ans)%t;b=(b+ans)%t;check(b,c,i);}
}
cout<<ans<<endl;
return 0;
}