1. 程式人生 > >hdu5919(主席樹OR分塊)

hdu5919(主席樹OR分塊)

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5919

思路:強制線上的主席樹,倒著插入數字,把當前位置貢獻值加1,如果這個數之前出現過把之前出現的那個位置貢獻值減1,然後就是兩次查詢就好了(不要管r版本的主席樹,根本沒有什麼用),分塊的話,速度很慢,算是卡過去的,塊的大小在1200-1800之間比較好,做法就是二分找每塊有多少不同的數,不在塊裡的暴力查詢就好了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(6666666)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
int n,m,a[200008],qw,rt[300008],c[300008],er;
struct as{
int l,r,sum;}tr[200008*50];
void add(int l,int r,int &x,int y,int pos,int ac)
{
    tr[++qw]=tr[y],tr[qw].sum+=ac,x=qw;
    if(l==r) return;
    int mid=(l+r)>>1;
    if(mid>=pos) add(l,mid,tr[x].l,tr[y].l,pos,ac);
    else add(mid+1,r,tr[x].r,tr[y].r,pos,ac);
}
int query(int l,int r,int x,int k)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(tr[tr[x].l].sum>=k) query(l,mid,tr[x].l,k);
    else query(mid+1,r,tr[x].r,k-tr[tr[x].l].sum);
}
int fid(int l,int r,int x,int L,int R)
{
    if(l>=L&&r<=R) return tr[x].sum;
    int mid=(l+r)>>1,res=0;
    if(L<=mid) res+=fid(l,mid,tr[x].l,L,R);
    if(R>mid) res+=fid(mid+1,r,tr[x].r,L,R);
    return res;
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    int res=1;
    while(t--)
    {
       cin>>n>>m;
       FOR(i,1,n) si(a[i]);
       REW(c,0),REW(rt,0);
       FOL(i,n,1)
       {
           if(!c[a[i]]) add(1,n,rt[i],rt[i+1],i,1);
           else add(1,n,er,rt[i+1],i,1),add(1,n,rt[i],er,c[a[i]],-1);
           c[a[i]]=i;
       }
       printf("Case #%d: ",res++);
       int zz=0,l,r,x,y,xc=0;
       while(m--)
       {
           si(x),si(y);
           l=min(((x+zz)%n)+1,((y+zz)%n)+1);
           r=max(((x+zz)%n)+1,((y+zz)%n)+1);
           //cout<<l<<" "<<r<<endl;
           zz=(fid(1,n,rt[l],l,r)+1)>>1;
           //cout<<zz<<endl;
           zz=query(1,n,rt[l],zz);//出現的下標位置肯定在【l,r】,不會找到r以後的下標
           if(!xc) printf("%d",zz);
           else printf(" %d",zz);
           xc++;
       }
       while(qw)
       {
            tr[qw].l= tr[qw].r=0;
            tr[qw--].sum=0;
       }
       puts("");
    }
    return 0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(6666666)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
int n,m,a[200008],qw,c[200008],er,l[200008],r[200008],d[200008],b[200008],e[200008],x[200008];
void build()
{
    int qw=1688,zz,er=1;
    zz=n/qw;
    if(n%qw!=0) zz++;
    FOR(i,0,zz-1) l[i+1]=i*qw+1,r[i+1]=(i+1)*qw;
    r[zz]=n;
    FOR(i,1,n)
    {
        if(i<=r[er]) d[i]=er;
        else d[i]=++er;
        e[i]=b[i]=c[a[i]];
        c[a[i]]=i;
    }
    FOR(i,1,zz) sort(b+l[i],b+r[i]+1);
}
int query(int ll,int rr)
{
    int res=0,zz=0,qw;
    for(int i=ll;i<=rr&&i<=r[d[ll]];i++) if(e[i]<ll) res++;
    for(int i=d[ll]+1;i<d[rr];i++)
    {
        x[i]=lower_bound(b+l[i],b+r[i]+1,ll)-b-l[i];
        res+=x[i];
    }
    if(d[ll]!=d[rr]){for(int i=l[d[rr]];i<=rr;i++) if(e[i]<ll) res++;}
    res=(res+1)>>1;
    for(int i=ll;i<=rr&&i<=r[d[ll]];i++)
    {
        if(e[i]<ll) zz++;
        if(zz==res) return i;
    }
    for(int i=d[ll]+1;i<d[rr];i++)
    {
        qw=zz;
        zz+=x[i];
        if(zz>=res)
        {
            for(int j=l[i];j<=r[i];j++)
            {
                if(e[j]<ll) qw++;
                if(qw==res) return j;
            }
        }
    }
    if(d[ll]!=d[rr])
    {
        for(int i=l[d[rr]];i<=rr;i++)
        {
            if(e[i]<ll) zz++;
            if(zz==res) return i;
        }
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    int t;
    cin>>t;
    int res=1;
    while(t--)
    {
       cin>>n>>m;
       FOR(i,1,n) si(a[i]);
       if(res==2) REW(c,0);
       build();
       printf("Case #%d: ",res++);
       int zz=0,l,r,xc=0;
       while(m--)
       {
           si(l),si(r);
           l=(l+zz)%n+1;
           r=(r+zz)%n+1;
           if(l>r) l^=r,r^=l,l^=r;
           zz=query(l,r);
           if(!xc) printf("%d",zz),xc++;
           else printf(" %d",zz);
       }
       puts("");
    }
    return 0;
}