例①:洛谷普通平衡树。。。题目不好复制。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<vector>
#define ll long long
#define llu unsigned ll
using namespace std;
const double alpha=0.75;
const int maxn=100100;
const int inf=0x3f3f3f3f;
struct node
{
int val,fa;
int son[2];
int si;
}t[maxn];
int tot,cnt,root,res[maxn];
bool balance(int q)
{
return (double)t[t[q].son[0]].si<=t[q].si*alpha&&(double)t[t[q].son[1]].si<=t[q].si*alpha;
}
int is_son(int q)
{
return q==t[t[q].fa].son[1];
}
void dfs(int q)
{
if(!q) return ;
dfs(t[q].son[0]);
res[++cnt]=q;
dfs(t[q].son[1]);
}
int build(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)>>1;
int q=res[mid];
int ls=build(l,mid-1);
int rs=build(mid+1,r);
t[q].son[0]=ls,t[ls].fa=q;
t[q].son[1]=rs,t[rs].fa=q;
t[q].si=t[ls].si+t[rs].si+1;
return q;
}
void re_build(int q)
{
cnt=0;
dfs(q);
int fa=t[q].fa,son=is_son(q),now=build(1,cnt);
t[now].fa=fa,t[fa].son[son]=now;
if(root==q) root=now;
}
int newnode(int x,int fa)
{
int p=++tot;
t[p].val=x;
t[p].son[0]=t[p].son[1]=0;
t[p].si=1;
t[p].fa=fa;
return p;
}
void init(void)
{
root=newnode(-inf,0);
t[1].son[1]=newnode(inf,1);
}
void _insert(int x)
{
int now=root;
while(1)
{
t[now].si++;
int son=(x>=t[now].val);
if(t[now].son[son]) now=t[now].son[son];
else
{
t[now].son[son]=newnode(x,now);
break;
}
}
int flag=0;
for(int i=tot;i;i=t[i].fa) if(!balance(i)) flag=i;
if(flag) re_build(flag);
}
int get_id(int x)
{
int now=root;
while(1)
{
if(t[now].val==x) return now;
else now=(x<t[now].val?t[now].son[0]:t[now].son[1]);
}
}
void del(int q)
{
if(t[q].son[0]&&t[q].son[1])
{
int tmp=t[q].son[0];
while(t[tmp].son[1]) tmp=t[tmp].son[1];
t[q].val=t[tmp].val;
q=tmp;
}
int now=(t[q].son[0]?t[q].son[0]:t[q].son[1]);
int son=is_son(q),fa=t[q].fa;
t[fa].son[son]=now;
t[now].fa=fa;
for(int i=fa;i;i=t[i].fa) t[i].si--;
if(root==q) root=now;
}
int get_rank(int x)
{
int now=root,ans=0;
while(now)
{
if(t[now].val<x) ans+=t[t[now].son[0]].si+1,now=t[now].son[1];
else now=t[now].son[0];
}
return ans;
}
int get_val(int k)
{
int now=root;
while(1)
{
if(t[t[now].son[0]].si+1==k) return t[now].val;
else if(t[t[now].son[0]].si>=k) now=t[now].son[0];
else k-=t[t[now].son[0]].si+1,now=t[now].son[1];
}
}
int get_front(int x)
{
int now=root,ans=-inf;
while(now)
{
if(t[now].val<x) ans=max(ans,t[now].val),now=t[now].son[1];
else now=t[now].son[0];
}
return ans;
}
int get_behind(int x)
{
int now=root,ans=inf;
while(now)
{
if(t[now].val>x) ans=min(ans,t[now].val),now=t[now].son[0];
else now=t[now].son[1];
}
return ans;
}
int main(void)
{
int n;
init();
scanf("%d",&n);
int pos,x;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&pos,&x);
if(pos==1)
_insert(x);
else if(pos==2)
x=get_id(x),del(x);
else if(pos==3)
printf("%d\n",get_rank(x));
else if(pos==4)
printf("%d\n",get_val(x+1));
else if(pos==5)
printf("%d\n",get_front(x));
else if(pos==6)
printf("%d\n",get_behind(x));
}
return 0;
}
例②:Serega and Fun CodeForces - 455D :
Serega loves fun. However, everyone has fun in the unique manner. Serega has fun by solving query problems. One day Fedor came up with such a problem.
You are given an array a consisting of n positive integers and queries to it. The queries can be of two types:
Make a unit cyclic shift to the right on the segment from l to r (both borders inclusive). That is rearrange elements of the array in the following manner:
a[l], a[l + 1], …, a[r - 1], a[r] → a[r], a[l], a[l + 1], …, a[r - 1].
Count how many numbers equal to k are on the segment from l to r (both borders inclusive).
Fedor hurried to see Serega enjoy the problem and Serega solved it really quickly. Let’s see, can you solve it?
Input
The first line contains integer n (1 ≤ n ≤ 105) — the number of elements of the array. The second line contains n integers a[1], a[2], …, a[n] (1 ≤ a[i] ≤ n).
The third line contains a single integer q (1 ≤ q ≤ 105) — the number of queries. The next q lines contain the queries.
As you need to respond to the queries online, the queries will be encoded. A query of the first type will be given in format: 1 l’i r’i. A query of the second type will be given in format: 2 l’i r’i k’i. All the number in input are integer. They satisfy the constraints: 1 ≤ l’i, r’i, k’i ≤ n.
To decode the queries from the data given in input, you need to perform the following transformations:
li = ((l’i + lastans - 1) mod n) + 1; ri = ((r’i + lastans - 1) mod n) + 1; ki = ((k’i + lastans - 1) mod n) + 1.
Where lastans is the last reply to the query of the 2-nd type (initially, lastans = 0). If after transformation li is greater than ri, you must swap these values.
Output
For each query of the 2-nd type print the answer on a single line.
Examples
Input
7
6 6 2 7 4 2 5
7
1 3 6
2 2 4 2
2 2 4 7
2 2 2 5
1 2 6
1 1 4
2 1 7 3
Output
2
1
0
0
Input
8
8 4 2 2 7 7 8 8
8
1 8 8
2 8 1 7
1 8 1
1 7 3
2 8 8 3
1 1 4
1 2 7
1 4 5
Output
2
0
强制在线,查询区间等于某个数的个数:
替罪羊树可维护一些区间的信息。
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<unordered_map>
#include<vector>
#define ll long long
#define llu unsigned ll
using namespace std;
const double alpha=0.75;
const int maxn=200100;
const int inf=0x3f3f3f3f;
struct node
{
int val;
int son[2];
int si,nodesi;
bool use;
unordered_map<int,int>mp;
}t[maxn];
void pushup(int p)
{
t[p].si=t[t[p].son[0]].si+t[t[p].son[1]].si+t[p].use;
t[p].nodesi=t[t[p].son[0]].nodesi+t[t[p].son[1]].nodesi+1;
t[p].mp.clear();
if(t[p].use) t[p].mp[t[p].val]++;
unordered_map<int,int>::iterator it;
for(it=t[t[p].son[0]].mp.begin();it!=t[t[p].son[0]].mp.end();it++)
t[p].mp[(*it).first]+=(*it).second;
for(it=t[t[p].son[1]].mp.begin();it!=t[t[p].son[1]].mp.end();it++)
t[p].mp[(*it).first]+=(*it).second;
}
int tot,cnt,root,top,bc[maxn],res[maxn],*pp;
bool balance(int q)
{
return (double)t[t[q].son[0]].nodesi<=t[q].nodesi*alpha&&(double)t[t[q].son[1]].nodesi<=t[q].nodesi*alpha;
}
int newnode(int x)
{
int p=0;
if(top) p=bc[top--];
else p=++tot;
t[p].val=x;
t[p].son[0]=t[p].son[1]=0;
t[p].si=t[p].nodesi=1;
t[p].use=true;
t[p].mp.clear();
t[p].mp[x]++;
return p;
}
int newbuild(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)>>1;
int p=newnode(res[mid]);
t[p].son[0]=newbuild(l,mid-1);
t[p].son[1]=newbuild(mid+1,r);
pushup(p);
return p;
}
void dfs(int q)
{
if(!q) return ;
dfs(t[q].son[0]);
if(t[q].use) res[++cnt]=q;
else bc[++top]=q;
dfs(t[q].son[1]);
}
int build(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)>>1;
int q=res[mid];
t[q].son[0]=build(l,mid-1);
t[q].son[1]=build(mid+1,r);
pushup(q);
return q;
}
void re_build(int *q)
{
cnt=0;
dfs(*q);
(*q)=build(1,cnt);
}
void _insert(int &p,int id,int x)
{
if(!p)
{
p=newnode(x);
pp=NULL;
return ;
}
t[p].si++;
t[p].nodesi++;
t[p].mp[x]++;
if(id<=t[t[p].son[0]].si+t[p].use)
_insert(t[p].son[0],id,x);
else _insert(t[p].son[1],id-t[t[p].son[0]].si-t[p].use,x);
if(!balance(p)) pp=&p;
}
void __insert(int id,int val)
{
_insert(root,id,val);
if(pp!=NULL) re_build(pp);
}
int del(int p,int id)
{
if(t[p].use&&t[t[p].son[0]].si+1==id)
{
t[p].use=false;
t[p].mp[t[p].val]--;
t[p].si--;
return t[p].val;
}
t[p].si--;
int res=0;
if(t[t[p].son[0]].si>=id)
res=del(t[p].son[0],id);
else res=del(t[p].son[1],id-t[t[p].son[0]].si-t[p].use);
t[p].mp[res]--;
return res;
}
int ask(int p,int l,int r,int val)
{
if(!p) return 0;
if(l<=1&&t[p].si<=r) return t[p].mp.count(val)?t[p].mp[val]:0;
int ans=0;
int res=t[t[p].son[0]].si+t[p].use;
if(l<=t[t[p].son[0]].si)
ans+=ask(t[p].son[0],l,r,val);
if(r>res)
ans+=ask(t[p].son[1],l-res,r-res,val);
if(t[p].use&&t[p].val==val&&l<=t[t[p].son[0]].si+1&&r>=t[t[p].son[0]].si+1)
ans++;
return ans;
}
int main(void)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&res[i]);
root=newbuild(1,n);
int m,op,l,r,k;
scanf("%d",&m);
int ans=0;
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&l,&r);
l=(l+ans-1)%n+1;
r=(r+ans-1)%n+1;
if(l>r) swap(l,r);
int x=del(root,r);
__insert(l,x);
}
else
{
scanf("%d%d%d",&l,&r,&k);
l=(l+ans-1)%n+1;
r=(r+ans-1)%n+1;
k=(k+ans-1)%n+1;
if(l>r) swap(l,r);
ans=ask(root,l,r,k);
printf("%d\n",ans);
}
}
return 0;
}