hdu5919(主席樹OR分塊)
阿新 • • 發佈:2018-11-16
題目連結: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; }