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 }