BZOJ 2724: [Violet 6]蒲公英

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2724

分块+二分。 首先离散化,维护ans[i][j]表示第i块到第j块之间的众数,然后对于询问l,r,在完整块的我们拿出来,然后暴力扫非完整块。

我们只要把相同的数排在一起,对于a[i],我们可以通过二分找到第一个在r之前的数的位置p和在第一个在l之后的数的位置q,p-q+1即为a[i]在询问l,r的出现次数。然后更新答案就好了。

(因为函数名起的太丑+手残傻逼了好久TAT。。。

#include<cstring>
#include<cctype>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define ll long long
#define maxn 50005
#define mm int(1e9+7)
using namespace std;
struct data{int v,p;
}d[maxn];
int h[maxn],a[maxn],L[maxn],R[maxn],l[maxn],r[maxn],c[maxn],belong[maxn],ans[205][205];
int n,m,cnt,block,lastans,x,y;
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int Find(int x){
    int l=1,r=n;
    while (l<=r){
        int mid=(l+r)/2;
        if (x==h[mid]) return mid;
        if (x<h[mid]) r=mid-1;
        else l=mid+1;
    }
    return l;
}
bool cmp(data a,data b){
    return a.v==b.v?a.p<b.p:a.v<b.v;
}
void pre(){
    rep(i,1,n) {
        d[i].v=a[i]; d[i].p=i;
    }
    sort(d+1,d+1+n,cmp);
    rep(i,1,n) {
        if (!L[d[i].v]) L[d[i].v]=i;
        R[d[i].v]=i;
    }
    rep(i,1,cnt){
        int tmp,mx=0; 
        clr(c,0);
        rep(j,l[i],n){
            c[a[j]]++;
            if (c[a[j]]>mx||(c[a[j]]==mx&&a[j]<tmp)) mx=c[a[j]],tmp=a[j];
            ans[i][belong[j]]=tmp;
        }
    } 
}
int findup(int l,int r,int x){
    int mid,tmp;
    while (l<=r){
        mid=(l+r)/2;
        if (d[mid].p>x) r=mid-1;
        else {tmp=mid; l=mid+1;}
    }
    return tmp;
}
int finddown(int l,int r,int x){
    int mid,tmp;
    while (l<=r){
        mid=(l+r)/2;
        if (d[mid].p<x) l=mid+1;
        else {tmp=mid; r=mid-1;} 
    }
    return tmp;
}
int que(int x,int y){
    int mx=0,tmp;
    if (belong[x]==belong[y]){
        rep(i,x,y) {
            int num=findup(L[a[i]],R[a[i]],y)-finddown(L[a[i]],R[a[i]],x)+1;
            if (num>mx||(num==mx&&a[i]<tmp)) mx=num,tmp=a[i];
        }
    }
    else {
        if (belong[x]+1<belong[y]){
            tmp=ans[belong[x]+1][belong[y]-1];
            mx=findup(L[tmp],R[tmp],y)-finddown(L[tmp],R[tmp],x)+1;
        }
        rep(i,x,r[belong[x]]){
            int num=findup(L[a[i]],R[a[i]],y)-finddown(L[a[i]],R[a[i]],x)+1;
            if (num>mx||(num==mx&&a[i]<tmp)) mx=num,tmp=a[i];
        }
        rep(i,l[belong[y]],y){
            int num=findup(L[a[i]],R[a[i]],y)-finddown(L[a[i]],R[a[i]],x)+1;
            if (num>mx||(num==mx&&a[i]<tmp)) mx=num,tmp=a[i];
        }
    }
    return tmp;
}
int main(){
       n=read(); m=read();
       rep(i,1,n) a[i]=read(),h[i]=a[i];
       sort(h+1,h+1+n);
       rep(i,1,n) a[i]=Find(a[i]);
    block=int(sqrt(n));
    cnt=n/block; if (n%block) cnt++;
    rep(i,1,cnt) l[i]=block*(i-1)+1,r[i]=block*i;
    int now=1; rep(i,1,n) {belong[i]=now;if (i%block==0) now++;}
    pre();
    lastans=0;
    rep(i,1,m){
        x=read(); y=read();
        x=(x+lastans-1)%n+1; y=(y+lastans-1)%n+1;
        if (x>y) swap(x,y);
        printf("%d\n",lastans=h[que(x,y)]);
    }
    return 0; 
}

 

posted on 2015-11-24 20:45  ctlchild  阅读(165)  评论(0编辑  收藏  举报

导航