HDU 5172(线段树单点更新,区间查询)

题意:给定一个数组N,然后给定M个询问,问区间[L,R]是否构成1~(R-L+1)的全排列。

思路:判断一个区间内是否是一个全排列,那么需要满足两个条件。1.区间和等于(R-L+2)*(R-L+1)/2; 2.该段区间内没有重复数字。第一个条件很好解决,用前缀和减一下就可以了。那第二个条件的话,先求出对于位置i的元素a[i],a[i]上一次出现的位置,然后线段树维护下最大值就可以了。因为如果这段区间内的数字,他上一次出现的最大位置都比L小,那么这段区间也就不会有数字重复。

代码

  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     int n,m;
 68     while(~scanf("%d%d",&n,&m))
 69     {
 70         mt(vis,0);
 71         for(int i=1;i<=n;i++)scanf("%d",a+i);
 72         sum[0]=0;
 73         for(int i=1;i<=n;i++)
 74         {
 75             if(!vis[a[i]])
 76             {
 77                 vis[a[i]]=i;
 78                 lpos[i]=0;
 79             }
 80             else
 81             {
 82                 lpos[i]=vis[a[i]];
 83                 vis[a[i]]=i;
 84             }
 85             sum[i]=sum[i-1]+a[i]*1LL;
 86         }
 87         for(int i=1;i<=n;i++)update(i,lpos[i],1,n,1);
 88         for(int i=0;i<m;i++)
 89         {
 90             int l,r;
 91             scanf("%d%d",&l,&r);
 92             if(sum[r]-sum[l-1]==1LL*(r-l+2)*(r-l+1)/2)
 93             {
 94                 if(query(l,r,1,n,1)<l)puts("YES");
 95                 else puts("NO");
 96             }
 97             else puts("NO");
 98         }
 99     }
100     return 0;
101 #ifdef Local
102     cerr << "time: " << (LL) clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
103 #endif
104 }
View Code

 

posted @ 2017-07-27 00:37  Kcl886  阅读(353)  评论(0编辑  收藏  举报