• UVA 12345 Dynamic len(set(a[LR]))


    题意:询问区间唯一元素个数,单点修改。

    分析

    借助Unique snowflakes, Can you answer these queries II的思想,唯一性可以借助元素上一次出现的位置来判断。

    对于询问(x,y),只要回答[x,y)区间内,上一次出现位置prv[i] < x的元素数量即可。

    对于修改来说,如果原来的a[x]的后继元素存在,则要修改后继的前驱。

    a[x]修改成y以后,找到x位置前的y出现位置,作为x位置的前驱,并修改x位置以后下一个y的前驱。

    寻找前驱后继可以用一个set保存(value,pos)的二元组,平方分解可以更暴力地找。

    目前已知实现方法有三种,1.线段树套平衡树,2.平方分解,3.BIT套函数式线段树。

    线段树套一个平衡树,想要偷懒试了试pb_ds里面的rb_tree,但是join的时候值域不能相交,并且只能nlognlogn建树。O((n+m)lognlogn)

    改成套SBT,可以做到nlogn建线段树,然后写挂了。(实际上是我不知道SBT删除的时候怎么maintain。也许改成Treap或者BST会过。)。O(nlogn + mlognlogn)

    平方分解,比较容易写,10s时限很稳。O(nlogn + m(N/BlogB+BlogB)) = O(nlogn + N^(3/2)log(N^(1/2)))

    BIT套函数式,好写,内存消耗大(UVA的内存没有限制吗?)。O(nlogn,mlognlogn)

    (实在过不了的话,因为暴力修改是O(1),可以水过...

    #include<bits/stdc++.h>
    #include<ext/pb_ds/assoc_container.hpp>
    #include<ext/pb_ds/tree_policy.hpp>
    
    using namespace std;
    using namespace __gnu_pbds;
    
    
    typedef pair<int,int> pii;
    
    typedef long long ll;
    
    
    const int maxn = 5e4+2;
    
    
    #define value first
    #define index second
    tree <pii,null_type> SET;
    
    #define para Node *(&o), int l = 0, int r = n
    #define lo (o->lch)
    #define ro (o->rch)
    #define Tvar int md = (l+r)>>1;
    #define lsn lo,l,md
    #define rsn ro,md,r
    #define insd x<=l&&r<=y
    
    const int maxd = 17;
    const int maxnds = maxd*maxn*maxd;
    struct Node
    {
        Node *lch,*rch;
        int s;
    }meo[maxnds];
    
    
    int a[maxn];
    int *const ps = (int*)(meo+1);
    int prv[maxn];
    int n;
    
    Node *root[maxn];
    
    Node *const nil = meo;
    Node *freeNode = nil;
    
    void build(int v,para)
    {
        *(++freeNode) = *o;
        o = freeNode;
        o->s++;
        if(r-l == 1) return;
        Tvar
        if(v < md) build(v,lsn);
        else build(v,rsn);
    }
    
    void inst(int v,int d,para)
    {
        if(o == nil){
            *(++freeNode) = *o;
            o = freeNode;
        }
        o->s += d;
        if(r-l == 1) return;
        Tvar
        if(v < md) inst(v,d,lsn);
        else inst(v,d,rsn);
    }
    
    Node *BIT[maxn];
    
    typedef vector<Node*> Prefix;
    
    Prefix X,Y;
    
    void q_pfx_bit(int x, Prefix &res)
    {
        res.clear();
        while(x > 0){
            res.push_back(BIT[x]);
            x &= x-1;
        }
    }
    
    void modify_bit(int x,int v,int d)
    {
        while(x <= n){
            inst(v,d,BIT[x]);
            x += x&-x;
        }
    }
    
    inline int cal_lft(Prefix &p)
    {
        int cnt = 0;
        for(auto &nd: p){
            cnt += nd->lch->s;
        }
        return cnt;
    }
    
    inline int cal_sum(Prefix &p)
    {
        int cnt = 0;
        for(auto &nd: p){
            cnt += nd->s;
        }
        return cnt;
    }
    
    
    #define dump(P,ch)
    for(auto &nd: P){
        nd = nd->ch;
    }
    
    int query(int v, int l = 0,int r = n)
    {
        if(r<=v) return cal_sum(Y)-cal_sum(X);
        Tvar
        if(v <= md) {
            dump(X,lch) dump(Y,lch)
            return query(v,l,md);
        }
        int tmp = cal_lft(Y)-cal_lft(X);
        dump(X,rch) dump(Y,rch)
        return tmp + query(v,md,r);
    }
    
    inline void modify(int x,int y)
    {
        modify_bit(x,prv[x],-1);
        modify_bit(x,prv[x]=y,1);
    }
    
    
    //#define LOCAL
    int main()
    {
    #ifdef LOCAL
        freopen("data.txt","r",stdin);
    #endif
        //cout<<maxnds;
        nil->lch = nil->rch = nil;
        root[0] = nil;
        int m;
        scanf("%d%d",&n,&m);
    
        for(int i = 1; i <= n; i++) {
            scanf("%d",a+i);
            prv[i] = ps[a[i]];
            ps[a[i]] = i;
            SET.insert(pii(a[i],i));
        }
    
        for(int i = 1; i <= n; i++){
            root[i] = root[i-1];
            build(prv[i],root[i]);
        }
    
        fill(BIT+1,BIT+n+1,nil);
        char op[2];
        int x,y;
        while(m--){
            scanf("%s%d%d",op,&x,&y); //0 based
            if(*op == 'Q'){
                q_pfx_bit(x,X);
                q_pfx_bit(y,Y);
                X.push_back(root[x]);
                Y.push_back(root[y]);
                printf("%d
    ",query(x+1));
            }
            else {
                x++;
                if(a[x] == y) continue; //...
                auto it = SET.lower_bound(pii(a[x],x+1));
                if(it != SET.end() && it->value == a[x]){
                    modify(it->index,prv[x]);
                }
    
                it = SET.lower_bound(pii(y,x));//找后继,需要保证(y,x)不存在
    
                if(it != SET.end() && it->value == y){
                    modify(it->index,x);
                }
    
                modify(x,(it != SET.begin() && (--it)->value == y)? it->index : 0);
    
                SET.erase(pii(a[x],x));
                SET.insert(pii(a[x] = y,x));
            }
        }
        return 0;
    }
  • 相关阅读:
    Xcode及模拟器SDK下载
    修改Navigation Bar上的返回按钮文本颜色,箭头颜色以及导航栏按钮的颜色
    NJKWebViewProgress ——webview进度条
    _tmain 和 main
    XSS原理
    逆向工程
    guide
    网络数据包
    Linux 文件系统 和文件属性
    Linux 文件系统
  • 原文地址:https://www.cnblogs.com/jerryRey/p/5023597.html
Copyright © 2020-2023  润新知