• P3521 [POI2011]ROT-Tree Rotations


    思路

    发现每个子树内的交换情况不会对子树外造成影响,所以可以利用贪心的思想,线段树合并找出当前子树的合并的最小值直接累加给答案即可

    我脑补的线段树合并貌似不太优秀的样子。。。每次都要新建节点,学习了直接把y合并到x上的想法,但是因为#define int long long的坏习惯导致MLE,最后还是要写内存池。。。

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <queue>
    #define int long long
    using namespace std;
    struct Node{
        int lson,rson,sz;
    }Seg[3000000];
    int Nodecnt,ans,min1,min2,n;
    queue<int> q;
    int getnew(void){
        if(q.size()){
            int t=q.front();
            q.pop();
            Seg[t].lson=Seg[t].rson=Seg[t].sz=0;
            return t;
        }
        return ++Nodecnt;
    }
    void throwin(int x){
        q.push(x);
    }
    void build(int l,int r,int &o,int val){
        // printf("%d %d %d %d
    ",l,r,o,val);
        if(!o)
            o=getnew();
        // printf("%d %d %d %d
    ",l,r,o,val);
        Seg[o].sz++;
        if(l==r){
            return;
        }
        int mid=(l+r)>>1;
        if(val<=mid)
            build(l,mid,Seg[o].lson,val);
        else
            build(mid+1,r,Seg[o].rson,val);
    }
    void merge(int &x,int y,int l,int r){
        if(x*y==0){
            x=x+y;
            return;
        }
        min1+=Seg[Seg[x].rson].sz*Seg[Seg[y].lson].sz;
        min2+=Seg[Seg[x].lson].sz*Seg[Seg[y].rson].sz;
        if(l==r){
            Seg[x].sz=Seg[x].sz+Seg[y].sz;
            return;
        }
        Seg[x].sz=Seg[x].sz+Seg[y].sz;
        int mid=(l+r)>>1;
        merge(Seg[x].lson,Seg[y].lson,1,mid);
        merge(Seg[x].rson,Seg[y].rson,mid+1,r);
        throwin(y);
        return;
    }
    int solve(void){
        int x;
        scanf("%lld",&x);
        if(!x){
            int lson,rson;
            lson=solve();
            rson=solve();
            min1=0;
            min2=0;
            int t=lson;
            merge(t,rson,1,n);
            // printf("%d %d
    ",min1,min2);
            ans+=min(min1,min2);
            return t;
        }
        else{
            int t=0;
            // printf("ok
    ");
            build(1,n,t,x);
            // printf("ok
    ");
            return t;
        }
        return 0;
    }
    signed main(){
        scanf("%lld",&n);
        solve();
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    hdu 1551 恶心的卡精度题
    ubuntu下升级firefox
    清理windows垃圾
    hdu 1575 矩阵快速幂
    右键菜单中添加用记事本打开(转)
    hdu 1525 博弈
    PHP字符串函数(转)
    笔试注意事项
    .NET 2.0面向对象编程揭秘 继承
    李开复:21世纪7种人才最抢手
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10556403.html
Copyright © 2020-2023  润新知