替罪羊树:

例①:洛谷普通平衡树。。。题目不好复制。

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值