[拒绝毒瘤的小清新系列] give you a tree
(小声)这其实是我读错某题之后自己出的一道题。。。。。。
正解也很简单啦,直接扫描线+线段树水过(考虑一个合法的区间正好有 siz-1 对树上相邻的点对)23333
#include<cstdio>
#include<vector>
#define ll long long
using namespace std;
const int N=300005;
#define pb push_back
#define lc (o<<1)
#define mid (l+r>>1)
#define rc ((o<<1)|1)
vector<int> g[N];
int mx[N*4],sum[N*4],tag[N*4],le,ri,w,n;
ll ans=0;
inline void maintain(int o){
mx[o]=max(mx[lc],mx[rc]);
sum[o]=(mx[lc]==mx[o]?sum[lc]:0)+(mx[rc]==mx[o]?sum[rc]:0);
}
inline void work(int o,int der){ tag[o]+=der,mx[o]+=der;}
inline void pushdown(int o){
if(tag[o]){
work(lc,tag[o]),work(rc,tag[o]);
tag[o]=0;
}
}
void ud1(int o,int l,int r){
if(l>=le&&r<=ri){ work(o,w); return;}
pushdown(o);
if(le<=mid) ud1(lc,l,mid);
if(ri>mid) ud1(rc,mid+1,r);
maintain(o);
}
void ud2(int o,int l,int r){
if(l==r){ sum[o]=1,mx[o]=l; return;}
pushdown(o);
if(le<=mid) ud2(lc,l,mid);
else ud2(rc,mid+1,r);
maintain(o);
}
inline void solve(){
for(int i=1;i<=n;i++){
le=i,ud2(1,1,n),le=w=1;
for(int j:g[i]) ri=j,ud1(1,1,n);
ans+=(ll)sum[1];
}
}
int main(){
scanf("%d",&n);
int uu,vv;
for(int i=1;i<n;i++){
scanf("%d%d",&uu,&vv);
if(uu>vv) swap(uu,vv);
g[vv].pb(uu);
}
solve();
printf("%lld\n",ans);
return 0;
}
我爱学习,学习使我快乐

浙公网安备 33010602011771号