ZOJ Monthly, August 2012 3633 Alice's present
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3633
题意:给一个数列,每次询问一个区间第一次出现两次的位置(从右向左)。
思路:开一个数组,记录当前值的左边第一次出现的位置。然后用线段树维护这个数组的区间最大值就行了。
View Code
#include<stdio.h> #include<string.h> #include<map> #include<utility> #include<algorithm> using namespace std; const int maxn = 500005; int as[maxn<<2],bs[maxn],cs[maxn],Hash[maxn],ds[maxn]; void build(int rt,int l,int r) { int m = (l + r) >> 1; if(l==r){ as[rt] = bs[l]; return; } build(rt<<1,l,m); build(rt<<1|1,m+1,r); as[rt]=max(as[rt<<1],as[rt<<1|1]); } int query(int rt,int l,int r,int L,int R) { int m = (l + r) >> 1; int k = 0,t = 0; if(L<=l && r<=R) return as[rt]; if(L<=m)k = query(rt<<1,l,m,L,R); if(R>m )t = query(rt<<1|1,m+1,r,L,R); return max(k,t); } int bitser(int x,int n) { int l = 1,r = n,m; while(l < r){ m = (l + r) >> 1; if(bs[m]==x)return m; if(bs[m]> x)r = m - 1; else l = m + 1; }return l; } int main() { int i,j,k,l,r,n; while(scanf("%d",&n)==1){ for(i = 1; i <= n; ++ i){ scanf("%d",&k); cs[i] = k; bs[i] = k; ds[i] = k; } sort(bs+1,bs+n+1); for(i = 1; i <= n; ++ i) cs[i] = bitser(cs[i],n); for(i = 1; i <= n; ++ i)Hash[i] = 0; for(i = 1; i <= n; ++ i){ bs[i] = Hash[cs[i]]; Hash[cs[i]] = i; } build(1,1,n); scanf("%d",&k); while(k--){ scanf("%d%d",&l,&r); j = query(1,1,n,l,r); if(!j||j<l)puts("OK"); else printf("%d\n",ds[j]); } puts(""); } return 0; }

浙公网安备 33010602011771号