退役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; }