zoukankan      html  css  js  c++  java
  • BZOJ 4399: 魔法少女LJJ 线段树合并 + 对数

    Description

    在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了
    LJJ感叹道“这里真是个迷人的绿色世界,空气清新、淡雅,到处散发着醉人的奶浆味;小猴在枝头悠来荡去,好不自在;各式各样的鲜花争相开放,各种树枝的枝头挂满沉甸甸的野果;鸟儿的歌声婉转动听,小河里飘着落下的花瓣真是人间仙境”
    SHY觉得LJJ还是太naive,一天,SHY带着自己心爱的图找到LJJ,对LJJ说:“既然你已经见识过动态树,动态仙人掌了,那么今天就来见识一下动态图吧”
    LJJ:“要支持什么操作?”
    SHY:“
    1.新建一个节点,权值为x。
    2.连接两个节点。
    3.将一个节点a所属于的联通快内权值小于x的所有节点权值变成x。
    4.将一个节点a所属于的联通快内权值大于x的所有节点权值变成x。
    5.询问一个节点a所属于的联通块内的第k小的权值是多少。
    6.询问一个节点a所属联通快内所有节点权值之积与另一个节点b所属联通快内所有节点权值之积的大小。
    7.询问a所在联通快内节点的数量
    8.若两个节点a,b直接相连,将这条边断开。
    9.若节点a存在,将这个点删去。

    LJJ:“我可以离线吗?”
    SHY:“可以,每次操作是不加密的,”
    LJJ:“我可以暴力吗?”
    SHY:“自重”
    LJJ很郁闷,你能帮帮他吗

    Input

    第一行有一个正整数m,表示操作个数。
    接下来m行,每行先给出1个正整数c。
    若c=1,之后一个正整数x,表示新建一个权值为x的节点,并且节点编号为n+1(当前有n个节点)。
    若c=2,之后两个正整数a,b,表示在a,b之间连接一条边。
    若c=3,之后两个正整数a,x,表示a联通快内原本权值小于x的节点全部变成x。
    若c=4,之后两个正整数a,x,表示a联通快内原本权值大于x的节点全部变成x。
    若c=5,之后两个正整数a,k,表示询问a所属于的联通块内的第k小的权值是多少。
    若c=6,之后两个正整数a,b,表示询问a所属联通快内所有节点权值之积与b所属联通快内所有节点权值之积的大小,
    若a所属联通快内所有节点权值之积大于b所属联通快内所有节点权值之积,输出1,否则为0。
    若c=7,之后一个正整数a,表示询问a所在联通块大小
    若c=8,之后两个正整数a,b,表示断开a,b所连接的边。
    若c=9,之后一个正整数a,表示断开a点的所有连边
    具体输出格式见样例

    Output

    这是一道语文题 + 高中数学题.
    这里最困难的是第 $6$ 问,询问两个联通快乘积的大小关系.
    显然不可以直接乘起来 (你想写高精度也行).
    高中数学告诉我们,$log_{x}(a imes b)=log_{x}(a)+log_{x}(b)$,而 $log_{x}$ 在 $x>=1$ 时是增函数.
    所以只需比较区间 $sum log$ 的大小就可以比较出乘积的大小.
    这个方法还真是听巧妙的.

    #include <cstdio>
    #include <algorithm> 
    #include <cmath> 
    using namespace std; 
    #define ls lson[x]
    #define rs rson[x]  
    #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 
    const int maxn=500000;  
    const int N=1000000000;  
    namespace IO {  
        char *p1,*p2,buf[100000];
        #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
        int rd() {
            int x=0; 
            char c=nc(); 
            while(c<48) c=nc(); 
            while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); 
            return x;
        }
    };   
    struct UFS { 
        int p[maxn];         
        void init() {
            for(int i=0;i<maxn;++i) p[i]=i; 
        }  
        int find(int x) {
            return p[x]==x?x:p[x]=find(p[x]); 
        }
    }tr; 
    int cnt;  
    int rt[maxn],lson[maxn*10],rson[maxn*10],num[maxn*10];      
    double de[maxn*10];
    int newnode() {
        return ++cnt;  
    } 
    void pushup(int x) {
        num[x]=num[ls]+num[rs]; 
        de[x]=de[ls]+de[rs];   
    }
    void update(int &x,int l,int r,int p,int v) {
        if(!x)x=newnode();                    
        if(l==r) {
            num[x]+=v, de[x]+=(double)v*(double)(log(p));      
            return;   
        } 
        int mid=(l+r)>>1;       
        if(p<=mid) update(ls,l,mid,p,v); 
        else update(rs,mid+1,r,p,v); 
        pushup(x); 
    }
    int merge(int x,int y) {
        if(!x||!y) return x+y;   
        num[x]+=num[y]; 
        de[x]+=de[y];    
        lson[x]=merge(lson[x],lson[y]);  
        rson[x]=merge(rson[x],rson[y]);    
        return x; 
    }    
    int less(int &x,int l,int r,int k) { 
        if(!x||l>=k) return 0;   
        int re=0; 
        if(r<k) {
            re=num[x],x=0; 
            return re;  
        }        
        if(l==r) return 0;   
        int mid=(l+r)>>1;     
        re+=less(ls,l,mid,k); 
        re+=less(rs,mid+1,r,k);       
        pushup(x); 
        return re;     
    }
    int bigger(int &x,int l,int r,int k) {
        if(!x||r<=k) return 0;  
        int re=0; 
        if(l>k) {
            re=num[x],x=0; 
            return re; 
        } 
        if(l==r) return 0; 
        int mid=(l+r)>>1; 
        re+=bigger(ls,l,mid,k); 
        re+=bigger(rs,mid+1,r,k); 
        pushup(x); 
        return re;   
    }
    int kth(int x,int l,int r,int k) {     
        if(l==r) return l;        
        int mid=(l+r)>>1;   
        if(k>num[ls]) return kth(rs,mid+1,r,k-num[ls]); 
        else return kth(ls,l,mid,k);        
    }
    int main() {   
        using namespace IO;  
        int m,cc=0;  
        m=rd(); 
        tr.init();    
        for(int cas=1;cas<=m;++cas) { 
            int op=rd(); 
            if(op==1) {
                int x=rd();  
                ++cc;  
                update(rt[cc],1,N,x,1);    
            }
            if(op==2) {
                int x,y,a,b; 
                x=rd(),y=rd(); 
                a=tr.find(x),b=tr.find(y);        
                if(a!=b) {
                    rt[b]=merge(rt[a],rt[b]);            
                    tr.p[a]=b;   
                }
            }       
            if(op==3) {
                int a,x,c=0; 
                a=rd(),x=rd(); 
                a=tr.find(a);   
                c=less(rt[a],1,N,x);         
                update(rt[a],1,N,x,c); 
            }
            if(op==4) {
                int a,x,c=0; 
                a=rd(),x=rd(); 
                a=tr.find(a); 
                c=bigger(rt[a],1,N,x);   
                update(rt[a],1,N,x,c);       
            }
            if(op==5) {
                int a,k;  
                a=rd(),k=rd(); 
                a=tr.find(a);              
                printf("%d
    ",kth(rt[a],1,N,k));   
            }
            if(op==6) {          
                int a,b; 
                a=rd(),b=rd(); 
                a=tr.find(a),b=tr.find(b);      
                if(de[rt[a]]>de[rt[b]]) printf("1
    "); 
                else printf("0
    "); 
            }
            if(op==7) { 
                int a; 
                a=rd(); 
                a=tr.find(a); 
                printf("%d
    ",num[rt[a]]);  
            } 
        }    
        return 0; 
    }
    

      

  • 相关阅读:
    06-排序【快速排序】算法学习
    05-排序【归并排序】算法学习
    【跨域CORS】的出现及解决办法
    【小工具】yml文件解析器
    【SpringBoot】has been blocked by CORS policy:The 'Access-Control-Allow-Origin' header contains multiple values 'xxx, xxx', but only one is allowed.
    【SpringBoot】java.lang.IllegalStateException: ApplicationEventMulticaster not initialized ....AnnotationConfigEmbeddedWebApplicationContext
    【图片分割器】Java完成图片分隔
    socket 服务器
    oracle 创建用户和授权
    解决1418
  • 原文地址:https://www.cnblogs.com/guangheli/p/11275836.html
Copyright © 2011-2022 走看看