2018 黑龙江省赛A Sequence Game 莫队+ST表

A Sequence Game
大意:求区间内的最大值与最小值中的数是否都出现过
看max-min+1是否等于区间数字种类数即可
前者预处理ST表
后者可用两种方法求出
1)莫队

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int>pii;
typedef pair<LL,LL>pll;
const int maxn=1e5;
const int mod=1e9+7;
const int oo=1e9;
int n,m,a[maxn+5],pos[maxn+5],len,L,R,Ans,num[maxn+5],ans[maxn+5];
int ma[maxn+5][30],mi[maxn+5][30],c[maxn+5];

struct node
{
    int l,r,id;
}b[maxn+5];
bool cmp(node a,node b)
{
    return pos[a.l]^pos[b.l]?pos[a.l]<pos[b.l]:((pos[a.l]&1)?a.r<b.r:a.r>b.r);
}
inline int read()
{
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9'){x = x * 10 + (c - '0'); c = getchar();}
    return x * f;
}
void init()
{
    for(int i=0;i<=n;i++) ma[i][0]=mi[i][0]=a[i],num[i]=0;

    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i<=n-(1<<j)+1;i++){
            ma[i][j]=max(ma[i][j-1],ma[i+(1<<(j-1))][j-1]);
            mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
        }
    }
}
int calu(int x,int y)
{
    int k=log(y-x+1)/log(2);
    int A=max(ma[x][k],ma[y-(1<<k)+1][k]);
    int B=min(mi[x][k],mi[y-(1<<k)+1][k]);
    return A-B+1;
}
void del(int x)
{
    //num[x]--;
    if(--num[x]==0) Ans--;
}
void add(int x)
{
    if(num[x]++==0) Ans++;
    //num[x]++;
}
int main()
{
    int _;_=read();
    while(_--){
        n=read();m=read();
        len=sqrt(n);
        for(int i=1;i<=n;i++) a[i]=read(),c[i]=a[i],pos[i]=i/len;
        init();
        sort(c+1,c+1+n);
        int k=unique(c+1,c+1+n)-c-1;
        for(int i=1;i<=n;i++) a[i]=lower_bound(c+1,c+k+1,a[i])-c;

        for(int i=1;i<=m;i++){
            b[i].l=read();b[i].r=read();
            b[i].id=i;
        }
        sort(b+1,b+1+m,cmp);

        L=1,R=0;Ans=0;
        for(int i=1;i<=m;i++){
            while(L<b[i].l){
                del(a[L++]);
            }
            while(L>b[i].l){
                //L--;
                add(a[--L]);
            }
            while(R<b[i].r){
                //R++;
                add(a[++R]);
            }
            while(R>b[i].r){
                del(a[R--]);
                //R--;
            }
            ans[b[i].id] = Ans==calu(b[i].l,b[i].r)?1:0;

        }

        for(int i=1;i<=m;i++){
            puts(ans[i]?"YES":"NO");

        }
    }
}

2)可持久化线段树

发布了61 篇原创文章 · 获赞 7 · 访问量 3185

猜你喜欢

转载自blog.csdn.net/qq_43914084/article/details/104098486