[分块 随机化] BZOJ 2223 [Coci 2009]PATULJCI


不会主席树 分块加随机化卡时过

但是另一道双倍经验就过不去啦233

这个坑以后再填


#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
  
inline char nc()
{
    static char buf[100005],*p1=buf,*p2=buf;
    if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
    return *p1++;
}
  
inline void read(int &x){
    char c=nc(),b=1;
    for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
    for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
  
int n,B,lim;
int sum[5005][10005];
int cnt,pos[300005];
int a[300005];
  
inline int Sum(int l,int r,int num){
    int lp=pos[l],rp=pos[r],ret=0;
    if (lp==rp)
    {
        for (int i=l;i<=r;i++)
            ret+=(a[i]==num);
        return ret;
    }
    for (int i=l;i<=lp*B;i++)
        ret+=(a[i]==num);
    for (int i=(rp-1)*B+1;i<=r;i++)
        ret+=(a[i]==num);
    if (lp+1<=rp-1)
        ret+=sum[rp-1][num]-sum[lp][num];
    return ret;
}
  
inline int random(int l,int r){
    return l+rand()*rand()%(r-l+1);
}
  
inline void Query(){
    #define Case 25
    int l,r,p,icnt,ret;
    read(l); read(r);
    icnt=(r-l+1)>>1;
    for (int it=1;it<=Case;it++)
    {
        p=random(l,r);
        ret=Sum(l,r,a[p]);
        if (ret>icnt){
            printf("yes %d\n",a[p]);
            return;
        }
    }
    printf("no\n");
}
  
int main()
{
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
    int Q;
    srand(15698);
    read(n); read(lim);
    B=(n-1)/5000+1;
    for (int i=1;i<=n;i++)
        pos[i]=(i-1)/B+1;
    cnt=(n-1)/B+1;
    for (int i=1;i<=n;i++)
    {
        read(a[i]);     
        sum[pos[i]][a[i]]++;
    }
    for (int i=1;i<=lim;i++)
        for (int j=1;j<=cnt;j++)
            sum[j][i]+=sum[j-1][i];
    read(Q);
    while (Q--)
        Query();
    return 0;
}



你可能感兴趣的:([分块 随机化] BZOJ 2223 [Coci 2009]PATULJCI)