noip2018 铺设道路

退役oier

day1t1见ancestor

一道ODT板子题都没人写?

主要(考场)思路

从小到大解决深度

每次解决一个深度,贡献就是与上一个深度之差乘上区间个数

之后就统统split

暴力枚举深度那里珂以用hash优化暴枚举的常数,懒得搞

复杂度因为每次split会删掉一个点,所以是严格nlogn

考场Code:

#include<bits/stdc++.h>
using namespace std;
#define gi getint()
inline int getint()
{
    int xi=0;
    bool f=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=='-'?f=1:0,ch=getchar();
    while(ch<='9'&&ch>='0')xi=xi*10+ch-48,ch=getchar();
    return f?-xi:xi;
}
struct node{
    int l,r;
    bool operator <(const node&b)const{
        return l<b.l;
    }
    node(int l,int r=0):l(l),r(r){}
};
set<node>p;
typedef set<node>::iterator P;
void split(int q)
{
    P tmp=p.upper_bound(q);--tmp;
    if(tmp==p.end()||tmp->r<q)return;
    node ttmp=*tmp;
    p.erase(tmp);
    if(ttmp.r>=q+1)p.insert(node(q+1,ttmp.r));
    if(ttmp.l<=q-1)p.insert(node(ttmp.l,q-1));
}
vector<int>v[100001];
int main()
{
    int n=gi;
    int maxi=0;
    for(int i=1,a;i<=n;i++)v[a=gi].push_back(i),maxi=max(maxi,a);
    p.insert(node(1,n));
    int ans=0,last=0;
    for(int i=0;i<=maxi;++i)
    {
        if(v[i].empty())continue;
        ans+=(i-last)*p.size();
        last=i;
        for(vector<int>::iterator j=v[i].begin();j!=v[i].end();++j)split(*j);
    }
    cout<<ans;
    return 0;
}
原文地址:https://www.cnblogs.com/LLCSBlog/p/10199425.html