http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3633
给你n个数,然后m个询问,每次询问区间[a,b]中从右到左最先出现重复的数字,比如
5
1 2 3 1 2
询问[1 5],那么答案就是2.因为2是第一次出现2次的。其中 3≤ n ≤ 500,000,1 ≤ m ≤ 50,000,数值<=2^31-1。
解法是,先把所有数字从小到大排序,相同的按出现的先后顺序排序。
更新时,对于每一个数x,如果前面的y==x的话,那么在线段树中,在x的坐标位置上赋值上y的坐标位置。
查询时,[a,b]就是查询区间[a,b]中大于等于a的最大值。如果最大值都小于a,那么就说明没有重复的。
比如上面的数据1 2 3 1 2,排序后就是:
1 1 2 2 3
pos:1 4 2 5 3
那么线段树中,[4,4]的值就是1,[5,5]的值就是2。其他线段没有值。
那么我们查询[1,4]的时候,显然最大值就是1,1大于等于[1,4]中的1,这就说明了有重复。因为线段[4,4]的值1实际上就说明了,原来在下标1到下标4有重复的数出现了。
还不清楚的话我们可以再试试查询区间[2,4],线段[2,4]在线段树上的最大值还是1,它小于2,没有重复。
这里说明了,[1,4]有重复的话,如果我们想要得到一个重复的区间,那么我们查询区间的左边界一定要小于等于1才有可能,这也是[2,4]没有重复区间的原因。
1 #include<iostream> 2 #include<string> 3 #include<stdio.h> 4 #include<memory.h> 5 #include<algorithm> 6 using namespace std; 7 int max(int a,int b){return a>b?a:b;} 8 9 struct node 10 { 11 int l; 12 int r; 13 int val; 14 }; 15 16 struct Point 17 { 18 int pos; 19 int val; 20 }; 21 22 Point x[500001]; 23 int n; 24 node tree[2500000]; 25 int X[500001]; 26 27 void build(int i,int l,int r) 28 { 29 tree[i].l=l; 30 tree[i].r=r; 31 tree[i].val=0; 32 if(l==r) 33 return; 34 int mid=(l+r)/2; 35 build(2*i,l,mid); 36 build(2*i+1,mid+1,r); 37 } 38 39 void updata(int i,int l,int r,int w) 40 { 41 if(tree[i].l>r || tree[i].r<l) 42 return; 43 if(tree[i].l>=l && tree[i].r<=r) 44 { 45 tree[i].val=w; 46 return; 47 } 48 updata(2*i,l,r,w); 49 updata(2*i+1,l,r,w); 50 tree[i].val=max(tree[2*i].val,tree[2*i+1].val); 51 } 52 53 int ans; 54 void find(int i,int l,int r) 55 { 56 if(tree[i].l>r || tree[i].r<l) 57 return; 58 if(tree[i].l>=l && tree[i].r<=r) 59 { 60 ans=max(ans,tree[i].val); 61 return; 62 } 63 find(2*i,l,r); 64 find(2*i+1,l,r); 65 } 66 67 int cmp(Point a,Point b) 68 { 69 if(a.val!=b.val) 70 return a.val<b.val; 71 else 72 return a.pos<b.pos; 73 } 74 75 int main() 76 { 77 int i,a,b,m; 78 freopen("D:\\in.txt","r",stdin); 79 while(scanf("%d",&n)==1) 80 { 81 for(i=0;i<n;i++) 82 { 83 scanf("%d",&x[i].val); 84 X[i+1]=x[i].val; //保护原始数据的顺序 85 x[i].pos=i+1; 86 } 87 build(1,1,n); 88 sort(x,x+n,cmp); 89 for(i=1;i<n;i++) 90 { 91 if(x[i].val==x[i-1].val) 92 { 93 updata(1,x[i].pos,x[i].pos,x[i-1].pos); 94 } 95 } 96 scanf("%d",&m); 97 while(m--) 98 { 99 scanf("%d%d",&a,&b); 100 ans=0; 101 find(1,a,b); 102 if(ans<a) 103 printf("OK\n"); 104 else 105 printf("%d\n",X[ans]); 106 } 107 printf("\n"); 108 } 109 return 0; 110 }