zoukankan      html  css  js  c++  java
  • 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);
        }
    }
  • 相关阅读:
    给VPS装桌面
    GIT免密码PUSH
    验证码类
    Url几个常用的函数
    PHP--关于模板的原理和解析
    管理员权限执行批处理和静默执行regsvr32注册
    linux 维护常见场景小命令 (未完待续)
    批处理定时重启print打印服务,解决打印机异常队列堆积
    Linux----LVM扩容磁盘空间
    6、Samba 服务器配置
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5007267.html
Copyright © 2011-2022 走看看