• Uva 3767 Dynamic len(set(a[L:R])) 树套树


    Dynamic len(set(a[L:R]))

    Time Limit: 20 Sec

    Memory Limit: 256 MB

    题目连接

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3767

    Description

    给你n个数,m次操作

    Q x y 询问[x+1,y]有多少个不同的数

    M x y 将第x+1个数修改成y

    Input

    n,50000 询问50000次,修改的y的数最大1e6

    Output

    Sample Input

    7 4
    1 2 1 3 2 1 4
    Q 1 6
    M 3 2
    Q 1 6
    Q 3 5

    Sample Output

    3
    2
    1

    HINT

    题意

    题解:

    树套树

    首先我们对于每个元素,将这个数的值修改成 这个数前面离最近的数,在哪儿

    比如样例 1 2 1 3 2 1 4

    我们可以看出 0 0 1 0 2 3 0

    然后我们每次的询问操作就是查询区间有多少个数小于l,这个就是平衡树或者主席树来解决就好了(划分树已经成为了时代的眼泪

    修改的话,就得树套树,然后我们再用set维护一下这个数后面的数是什么,前面的数是什么就好了

    注意,修改会修改3个数哦~

    代码:

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<map>
    #include<cstring>
    #include<set>
    #include<ctime>
    using namespace std;
    inline long long read()
    {
        long long x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    #define maxn 1500005
    int tmp=0;
    int a[maxn];
    int c[maxn];
    int b[maxn];
    int n,m;
    set<int> H[maxn];
    ////////////////treap
    struct Treap
    {
        int root[maxn],sz,s[maxn],ls[maxn],rs[maxn],v[maxn],w[maxn],rnd[maxn];
        void init()
        {
            memset(root,0,sizeof(root));
            sz=0;
        }
        void Updata(int k)
        {
            s[k]=s[ls[k]]+s[rs[k]]+w[k];
        }
        void Rturn(int &k)
        {
            int t;
            t=ls[k],ls[k]=rs[t],rs[t]=k,s[t]=s[k];
            Updata(k);k=t;
        }
        void Lturn(int &k)
        {
            int t;
            t=rs[k],rs[k]=ls[t],ls[t]=k,s[t]=s[k];
            Updata(k);k=t;
        }
        void Insert(int &k,int num)
        {
            if(!k)
            {
                k=++sz;s[k]=w[k]=1;ls[k]=rs[k]=0;rnd[k]=rand();
                v[k]=num;return;
            }
            s[k]++;
            if(v[k]==num)w[k]++;
            else if(num<v[k])
            {
                Insert(ls[k],num);
                if(rnd[ls[k]]<rnd[k])
                    Rturn(k);
            }
            else
            {
                Insert(rs[k],num);
                if(rnd[rs[k]]<rnd[k])
                    Lturn(k);
            }
        }
        void Del(int &k,int num)
        {
            if(v[k]==num)
            {
                if(w[k]>1){
                    w[k]--;
                    s[k]--;
                    return;
                }
                if(ls[k]*rs[k]==0)
                    k=ls[k]+rs[k];
                else if(rnd[ls[k]]<rnd[rs[k]])
                    Rturn(k),Del(k,num);
                else
                    Lturn(k),Del(k,num);
            }
            else if(num<v[k]){
                Del(ls[k],num);
                s[k]--;
            }
            else{
                Del(rs[k],num);
                s[k]--;
            }
        }
        void Find(int k,int num)
        {
            if(!k)return;
            if(v[k]<=num){
                tmp+=s[ls[k]]+w[k];
                Find(rs[k],num);
            }
            else Find(ls[k],num);
        }
    }Tr;
    
    /////////////////////
    
    /////////////////////线段树
    int lowbit(int x)
    {
        return x&(-x);
    }
    void Bit_updata(int x,int v)
    {
        if(x==0)return;
        for(;x<=n;x+=lowbit(x))
            Tr.Insert(Tr.root[x],v);
    }
    void Bit_change(int x,int v)
    {
        if(x==0)return;
        for(;x<=n;x+=lowbit(x))
            Tr.Del(Tr.root[x],v);
    }
    void Bit_query(int x,int num)
    {
        if(x<=0)return;
        for(;x;x-=lowbit(x))
            Tr.Find(Tr.root[x],num);
    }
    ///////////////////////////
    
    void change(int x,int y)
    {
        Bit_change(x,a[x]);
        H[b[x]].erase(x);
        int T = *H[b[x]].upper_bound(x);
        if(T!=n+5)
        {
            Bit_change(T,x);
            Bit_updata(T,a[x]);
            a[T]=a[x];
        }
        b[x]=y;
        T = *--H[b[x]].upper_bound(x);
        a[x]=T;int MM = T;
        Bit_updata(x,a[x]);
        H[y].insert(x);
        T = *H[b[x]].upper_bound(x);
        if(T!=n+5)
        {
            Bit_change(T,MM);
            Bit_updata(T,x);
            a[T]=x;
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<1000005;i++)
            H[i].insert(0),H[i].insert(n+5);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i]);
            H[b[i]].insert(i);
        }
        for(int i=1;i<=n;i++)
        {
            a[i]=c[b[i]];
            c[b[i]]=i;
            Bit_updata(i,a[i]);
        }
        char op[5];int x,y;
        for(int i=1;i<=m;i++)
        {
            scanf("%s%d%d",op,&x,&y);x++;
            if(op[0]=='Q')
            {
                int Ans1,Ans2;
                tmp = 0,Bit_query(y,x-1),Ans1=tmp;
                tmp = 0,Bit_query(x-1,x-1),Ans2=tmp;
                printf("%d
    ",Ans1-Ans2);
            }
            else
                change(x,y);
        }
    }
  • 相关阅读:
    segmentedControl设置字体和字体颜色问题
    iOS 8 自适应 Cell
    视频聊天 Demo
    tensorflow生成随机数的操作 tf.random_normal & tf.random_uniform & tf.truncated_normal & tf.random_shuffle
    python selenium点滴
    cmd 字符串截取
    cmd 获取 拖拽文件名
    cmd for 用法
    cmd dos bat 深度变量文件夹指定文件
    bat cmd dos 通过拖拽参数 上传 截取拖拽上传文件名
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5007267.html
Copyright © 2020-2023  润新知