[HDU-5172] 单点查询线段树
题意:
给你一个长度为n的数组v[],有m次询问,问你在区间[L,R]中是否包含区间[1,R-L+1]的全部数字,如果是输出YES,否则输出NO
题解:
区间[1,R-L+1]与区间[L,R]的长度一样,所以如果输出YES,那么区间[L,R]中的数字就是1到R-L+1数字的全排列形式。那么就判断这个满足下面两点就行
1、区间和等于(R-L+2)*(R-L+1)/2;
2.该段区间内没有重复数字。
对于第一点我们只需要用前缀和就可以。
对于第二点,我们可以用lpos[i]表示输入的v[i]这个数字上一次(就是在区间[1,i-1])出现的最大位置,如果之前没有出现过就初始为0.这样的话对于区间内是否有重复数字,我们只需要查找一下下标为[L,R]的这些位置的值lpos[i]的最大值是否大于L,大于的话那么也就意味着这个区间内出现重复值了,就输出NO
代码:
1 #include <iostream> 2 #include <queue> 3 #include <stack> 4 #include <cstdio> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <bitset> 9 #include <algorithm> 10 #include <cmath> 11 #include <cstring> 12 #include <cstdlib> 13 #include <string> 14 #include <sstream> 15 #include <time.h> 16 #define x first 17 #define y second 18 #define pb push_back 19 #define mp make_pair 20 #define lson l,m,rt*2 21 #define rson m+1,r,rt*2+1 22 #define mt(A,B) memset(A,B,sizeof(A)) 23 #define lowbit(x) (x&(-x)) 24 using namespace std; 25 typedef long long LL; 26 typedef unsigned long long ull; 27 const double PI = acos(-1); 28 const int N=1e6+10; 29 //const int M=1e6+10; 30 const LL mod=1e9; 31 const int inf = 0x3f3f3f3f; 32 const LL INF=0x3f3f3f3f3f3f3f3fLL; 33 const double esp=1e-10; 34 int a[N],vis[N],lpos[N],Ma[N<<2]; 35 LL sum[N]; 36 void pushUp(int rt) 37 { 38 Ma[rt]=max(Ma[rt*2],Ma[rt*2+1]); 39 } 40 void update(int pos,int val,int l,int r,int rt) 41 { 42 if(l==r) 43 { 44 Ma[rt]=val;return; 45 } 46 int m=(l+r)/2; 47 if(pos<=m)update(pos,val,lson); 48 else update(pos,val,rson); 49 pushUp(rt); 50 } 51 int query(int L,int R,int l,int r,int rt) 52 { 53 int ans=-inf; 54 if(L<=l&&r<=R)return Ma[rt]; 55 int m=l+(r-l)/2; 56 if(L<=m)ans=max(ans,query(L,R,lson)); 57 if(R>m)ans=max(ans,query(L,R,rson)); 58 return ans; 59 } 60 int main() 61 { 62 #ifdef Local 63 freopen("data.h","r",stdin); 64 #endif 65 //ios::sync_with_stdio(false); 66 //cin.tie(0); 67 68 #ifdef Local 69 cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; 70 #endif 71 }
代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<math.h> 6 #include<vector> 7 #include<queue> 8 #include<stack> 9 #include<map> 10 using namespace std; 11 typedef long long ll; 12 const int maxn=1e6+10; 13 const int INF=0x3f3f3f3f; 14 const double eps=1e-10; 15 #define mt(A,B) memset(A,B,sizeof(A)) 16 #define lson l,m,rt*2 17 #define rson m+1,r,rt*2+1 18 ll v[maxn],vis[maxn],lpos[maxn],tree[maxn<<2],sum[maxn]; 19 void pushup(ll rt) 20 { 21 tree[rt]=max(tree[rt<<1],tree[rt<<1+1]); 22 } 23 void update(ll pos,ll val,ll l,ll r,ll rt) 24 { 25 if(l==r) 26 { 27 tree[rt]=val; 28 return ; 29 } 30 ll m=(l+r)>>1; 31 if(pos<=m) update(pos,val,lson); 32 else update(pos,val,rson); 33 pushup(rt); 34 } 35 ll query(ll L,ll R,ll l,ll r,ll rt) 36 { 37 ll ans=0; 38 if(L<=l && R>=r) 39 return tree[rt]; 40 ll m=(l+r)>>1; 41 if(L<=m) ans=max(ans,query(L,R,lson)); 42 if(R>m) ans=max(ans,query(L,R,rson)); 43 return ans; 44 } 45 int main() 46 { 47 ll n,m; 48 while(~scanf("%lld%lld",&n,&m)) 49 { 50 mt(vis,0); 51 for(ll i=1; i<=n; i++) 52 scanf("%lld",&v[i]); 53 sum[0]=0; 54 for(ll i=1; i<=n; i++) 55 { 56 if(!vis[v[i]]) 57 { 58 vis[v[i]]=i; 59 lpos[i]=0; 60 } 61 else 62 { 63 lpos[i]=vis[v[i]]; 64 vis[v[i]]=i; 65 } 66 sum[i]=sum[i-1]+v[i]*1LL; 67 } 68 for(ll i=1; i<=n; i++)update(i,lpos[i],1,n,1); 69 for(ll i=0; i<m; i++) 70 { 71 ll l,r; 72 scanf("%lld%lld",&l,&r); 73 if(sum[r]-sum[l-1]==1LL*(r-l+2)*(r-l+1)/2) 74 { 75 if(query(l,r,1,n,1)<l)printf("YES\n"); 76 else printf("NO\n"); 77 } 78 else printf("NO\n"); 79 } 80 } 81 return 0; 82 }