zoukankan      html  css  js  c++  java
  • Luogu P4331 [BOI2004]Sequence 数字序列 (左偏树论文题)

    清晰明了%%% Fairycastle的博客

    个人习惯把size什么的存在左偏树结点内,这样在外面好写,在里面就是模板(只用修改update).

    可以对比一下代码(好像也差不多…)

    MY CODE

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1000005;
    struct lt {
    	int ls, rs, v, d, sz;
    }t[MAXN];
    int n, m, l[MAXN], r[MAXN], st[MAXN], a[MAXN], b[MAXN]; //st存栈内根节点编号
    inline void upd(int x) {
    	if(t[t[x].ls].d < t[t[x].rs].d) swap(t[x].ls, t[x].rs);
    	t[x].d = t[t[x].rs].d + 1;
    	t[x].sz = t[t[x].ls].sz + t[t[x].rs].sz + 1;
    }
    int merge(int x, int y) {
        if(!x || !y) return x + y;
        if(t[y].v > t[x].v) swap(x, y);
        t[x].rs = merge(t[x].rs, y);
        upd(x);
        return x;
    }
    inline int pop(int x) {
        int l = t[x].ls, r = t[x].rs;
        t[x].ls = t[x].rs = t[x].d = 0; t[x].sz = 1;
        return merge(l, r);
    }
    int main () {
        t[0].d = -1;
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), a[i] -= i;
    	for(int i = 1; i <= n; ++i) {
    		st[++m] = i; l[m] = r[m] = i;
    		t[i] = (lt) { 0, 0, a[i], 0, 1 };
    		while(m > 1 && t[st[m-1]].v > t[st[m]].v) {
    			--m;
    			st[m] = merge(st[m], st[m+1]);
    			r[m] = r[m+1];
    			while(t[st[m]].sz<<1 > r[m]-l[m]+2)
    				st[m] = pop(st[m]);
    		}
    	}
    	long long ans = 0;
    	for(int i = 1; i <= m; ++i)
    		for(int j = l[i]; j <= r[i]; ++j)
    			ans += abs(a[j]-(b[j]=t[st[i]].v));
    	printf("%lld
    ", ans);
    	for(int i = 1; i <= n; ++i) printf("%d ", b[i] + i);
    }
    
    

    Other CODE

    #include<bits/stdc++.h>
    #define ll long long
    #define in inline
    #define rint register int
    #define N 1000010
    using namespace std;
    int n,m;
    int d[N],ls[N],rs[N];
    ll a[N],b[N],ans;
    struct node{
        int rt,l,r,siz;
        ll w;
    }s[N];
    in ll read()
    {
        ll 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;
    }
    in int merge(int x,int y)
    {
        if(x==0||y==0) return x+y;
        if(a[x]<a[y]) swap(x,y);
        rs[x]=merge(rs[x],y);
        if(d[ls[x]]<d[rs[x]]) swap(ls[x],rs[x]);
        d[x]=d[rs[x]]+1;
        return x;
    }
    in void work()
    {
        for(rint i=1;i<=n;i++)
        {
            s[++m]=(node) { i,i,i,1,a[i] };
            while(m>1&&s[m].w<s[m-1].w)
            {
                m--;
                s[m].rt=merge(s[m].rt,s[m+1].rt);
                s[m].siz+=s[m+1].siz; 
                s[m].r=s[m+1].r;
                while(s[m].siz>(s[m].r-s[m].l+1+2)>>1)//向上取整 
                {
                    s[m].siz--;
                    s[m].rt=merge(ls[s[m].rt],rs[s[m].rt]);
                }
                s[m].w=a[s[m].rt];
            }
        }
        for(rint i=1;i<=m;i++)
            for(rint j=s[i].l;j<=s[i].r;j++) 
                b[j]=s[i].w,ans+=abs(a[j]-b[j]);
    }
    int main()
    {
        d[0]=-1; n=read();
        for(rint i=1;i<=n;i++) a[i]=read()-i;
        work();
        printf("%lld
    ",ans);
        for(rint i=1;i<=n;i++) printf("%lld ",b[i]+i);
        return 0;
    }
    
  • 相关阅读:
    Python笔记_函数,模块,包的关系
    「GXOI / GZOI2019」宝牌一大堆
    「BalticOI 2020」村庄 (贪心)
    CF Round #635 Div.1 Chiori and Doll Picking (hard version)
    「BalticOI 2020」病毒
    「BalticOI 2020」小丑
    「BalticOI 2020」混合物
    k短路
    「JSOI2019」神经网络
    「NOI2020」时代的眼泪
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12039339.html
Copyright © 2011-2022 走看看