2018 东北省赛 A Sequence Game (ST 莫队算法 or 主席树 )

7218: A Sequence Game

时间限制: 1 Sec  内存限制: 128 MB
提交: 209  解决: 54
[提交] [状态] [讨论版] [命题人:admin]

题目描述

One day, WNJXYK found a very hard problem on an Online Judge. This problem is so hard that he had been thinking about the solutions for a couple of days. And then he had a surprise that he misunderstood that problem and easily figured out a solution using segment tree. Now he still wonders that solution for the misread problem.
There is a sequence with N positive integers A1,A2,…,An and M queries. Each query will give you an interval [L,R] and require an answer with YES / NO indicates that whether the numbers in this interval are continuous in its integer range. 
Let us assume that the maximal number in an interval is mx and the minimal   number is mi. The numbers in this interval are continuous in its integer range means that each number from mi to mx appears at least once in this interval.

输入

The input starts with one line contains exactly one positive integer T which is the number of test cases. And then there are T cases follow.
The first line contains two positive integers n,m which has been explained above.
The second line contains n positive integers A1,A2,…,An.
Then there will be m lines followed. Each line contains to positive numbers Li,Ri indicating that the i th query’s interval is [Li,Ri].

输出

For each test case, output m line.
Each of following m lines contains a single string “YES”/ “NO” which is the answer you have got.

样例输入

2
3 3
3 1 2 
2 3
1 3
1 2
5 3
1 2 2 4 5 
1 5
1 3
3 3

样例输出

YES
YES
NO
NO
YES
YES

提示

T=5
1≤n≤100000
1≤Ai≤10^9
1≤m≤100000
The input file is very large, so you are recommend to use scanf() and printf() for IO.

来源/分类

2018黑龙江省赛 

题目就是给你一个区间问你区间是否连续,当时参加比赛的时候这两个算法都不会,当时也就是会简单的线段树。现在看到题

就想到了这两个算法,无奈还是写残了,调试了好长时间,拿了一份代码对照了半天,发现我俩的思路一样,但是我的却一直超时,本来以为n*sqrt(n)过不去,结果还是过去了。。

后来发现过不去的原因是因为莫队分块的时候块的标号写v错了,我写成了i/块长。。无语。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define N 100105
int a[N],b[N];

struct node
{
    int l,r,id;
    int block;
    friend bool operator <(node x,node y)
    {
        if(x.block!=y.block)return x.block<y.block;
        else return x.r<y.r;
    }
}Q[N];

int p[N];
void lsh(int n)
{
    sort(b+1,b+1+n);
    int cnt=unique(b+1,b+1+n)-b-1;
    for(int i=1;i<=n;i++) p[i]=lower_bound(b+1,b+1+cnt,a[i])-b;
}

int c1[25][N];
int c2[25][N];

void ST(int n)
{
    int k=log2(n);
    for(int i=1;i<=n;i++)
    {
        c1[0][i]=a[i];
        c2[0][i]=a[i];
    }
    for(int i=1;i<=k;i++)
    {
        for(int j=1;j+(1<<i)-1<=n;j++)
        {
            c1[i][j]=max(c1[i-1][j],c1[i-1][j+(1<<(i-1))]);
            c2[i][j]=min(c2[i-1][j],c2[i-1][j+(1<<(i-1))]);
        }
    }
}

int query_min(int l,int r)
{
    int kk=log2(r-l+1);
    return min(c2[kk][l],c2[kk][r-(1<<kk)+1]);
}

int query_max(int l,int r)
{
    int kk=log2(r-l+1);
    return max(c1[kk][l],c1[kk][r-(1<<kk)+1]);
}

int ans[N];
int tot;
int vis[N];

void add(int x)
{
    if(vis[p[x]]==0)tot++;
    vis[p[x]]++;
}

void sub(int x)
{
    vis[p[x]]--;
    if(vis[p[x]]==0) tot--;
}

int main()
{
   int t,n;
   cin>>t;
   while(t--)
   {
       int m;
       tot=0;
       memset(vis,0,sizeof(vis));
       scanf("%d%d",&n,&m);
       for(int i=1;i<=n;i++)
       {
           scanf("%d",&a[i]);
           b[i]=a[i];
       }
       lsh(n);
       ST(n);
       int len=(int)sqrt(n);
       for(int i=1;i<=m;i++)
       {
           scanf("%d%d",&Q[i].l,&Q[i].r);
           Q[i].id=i;
           Q[i].block=Q[i].l/len;
       }
       sort(Q+1,Q+1+m);
       int r=0,l=1;
       for(int i=1;i<=m;i++)
       {
           int ql=Q[i].l;
           int qr=Q[i].r;
           while(r<qr)add(++r);
           while(r>qr)sub(r--);
           while(l<ql)sub(l++);
           while(l>ql)add(--l);
           int yy=query_max(ql,qr);
           int xx=query_min(ql,qr);
           if(yy-xx+1==tot) ans[Q[i].id]=1;
           else ans[Q[i].id]=0;

       }
       for(int i=1;i<=m;i++)
       {
           if(ans[i])puts("YES");
           else puts("NO");
       }
   }
}

用主席树做就是查询区间不同数的个数是否等于区间最大值减去最小值+1,明天把代码补出来。

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/82503487