Description
数列A1,A2, ...,AN,Q 个询问(Li;Ri),ALi,ALi+1,...,ARi 是否互不相同
Input
第1 行,2 个整数N;Q,
第2 行,N 个整数A1,A2,...,AN
Q 行,每行2 个整数Li;Ri
Output
对每个询问输出一行,“Yes” 或者“No”
Sample Input
4 2
1 2 3 2
1 3
2 4
Sample Output
Yes
No
Hint
对于50% 的数据,N,Q<=10^3
对于100% 的数据,1<=N,Q<=10^5; 1<=Ai<=N; 1<=Li<=Ri<=N
【分析】(感谢nodgd同学提供)
1.对于每个位置的数字v[i],next[i]记录右边第一个和自己相同的数字的位置下标, last[x]记录最左边一次出现数字x的位置下标。求出这两个数组的方法就和存边一模一样。
2.把每次提问双关键字排序。
3.把所有的last[x]标上1,同时用树状数组维护这一些"1"的前缀和
4.每次提问区间l到r,先把l左边的所有"1"都转移到它的next,也就是让l的左边为0,然后树状数组求出位置下标1到r这一段的前缀和sum,即这一段有多少个"1"。如果sum==r-l+1就说明这一段满满的都是"1",那么这段区间的ans是"Yes";否则"No"。
5.把所有区间恢复到原来的顺序,依次输出答案
(注:其实这道题跟HZOI的赏花那道题很类似,,传送门:http://blog.youkuaiyun.com/greatwjj/article/details/12288251)
【代码】
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define _lowbit(x) (x&(-x))
using namespace std;
const int MAXN=100005;
struct node{int x,y,rank;}Query[MAXN];
int N,Q,v[MAXN],c[MAXN],next[MAXN],last[MAXN],maxv;
bool ans[MAXN];
void _in(int &x)
{
char t=getchar();
while(t<'0'||'9'<t) t=getchar();
for(x=0;'0'<=t&&t<='9';x=x*10+t-'0',t=getchar());
}
void _qst_xy(int l,int r)
{
int i=l,j=r,mx=Query[(i+j)>>1].x,my=Query[(i+j)>>1].y;
while(i<=j)
{
while(Query[i].x<mx||(Query[i].x==mx&&Query[i].y<my)) i++;
while(Query[j].x>mx||(Query[j].x==mx&&Query[j].y>my)) j--;
if(i<=j)
{
swap(Query[i],Query[j]);
i++;j--;
}
}
if(l<j) _qst_xy(l,j);
if(i<r) _qst_xy(i,r);
}
void _init()
{
_in(N);_in(Q);
for(int i=1;i<=N;i++)
{
_in(v[i]);
maxv=max(maxv,v[i]);
}
for(int i=1;i<=Q;i++)
{
_in(Query[i].x);
_in(Query[i].y);
Query[i].rank=i;
}
_qst_xy(1,Q);
}
void _solve()
{
for(int i=N;i;i--)
{
next[i]=last[v[i]];
last[v[i]]=i;
}
for(int i=1;i<=maxv;i++)
if(last[i]!=0)
for(int j=last[i];j<=N;j+=_lowbit(j))
c[j]++;
for(int i=1;i<=Q;i++)
{
for(int k=max(1,Query[i-1].x);k<Query[i].x;k++)
{
for(int j=k;j<=N;j+=_lowbit(j))
c[j]--;
if(next[k]!=0)
for(int j=next[k];j<=N;j+=_lowbit(j))
c[j]++;
}
int temp=0;
for(int j=Query[i].x-1;j;j-=_lowbit(j))
temp-=c[j];
for(int j=Query[i].y;j;j-=_lowbit(j))
temp+=c[j];
ans[Query[i].rank]=(temp==(Query[i].y+1-Query[i].x))?true:false;
}
for(int i=1;i<=Q;i++)
printf((ans[i])?"Yes\n":"No\n");
}
int main()
{
_init();
_solve();
return 0;
}