题解:
题解居然是LCT……受教了
把所有区间按照端点排序,动态维护目前有重叠的区间,用LCT维护即可。
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 using namespace std;
8 typedef long long ll;
9 struct node{
10 int son[2],fa,sz1,sz2,rev;
11 }t[500001];
12 struct task{
13 int op,u,v,x;
14 task(int _op=0,int _u=0,int _v=0,int _x=0){
15 op=_op,u=_u,v=_v,x=_x;
16 }
17 friend bool operator <(task a,task b){
18 return a.x==b.x?a.op<b.op:a.x<b.x;
19 }
20 }q[500001];
21 int n,u,v,l,r,cnt=0,top,s[500001];
22 ll ans;
23 int lr(int u){
24 return t[t[u].fa].son[1]==u;
25 }
26 int ntrt(int u){
27 return t[t[u].fa].son[0]==u||t[t[u].fa].son[1]==u;
28 }
29 void pushup(int u){
30 t[u].sz1=t[t[u].son[0]].sz1+t[t[u].son[1]].sz1+t[u].sz2+1;
31 }
32 void getrev(int u){
33 swap(t[u].son[0],t[u].son[1]);
34 t[u].rev^=1;
35 }
36 void pd(int u){
37 if(t[u].rev){
38 if(t[u].son[0])getrev(t[u].son[0]);
39 if(t[u].son[1])getrev(t[u].son[1]);
40 t[u].rev=0;
41 }
42 }
43 void rotate(int u){
44 int f=t[u].fa,ff=t[f].fa,ch=lr(u);
45 if(ntrt(f))t[ff].son[t[ff].son[1]==f]=u;
46 t[f].son[ch]=t[u].son[ch^1];
47 t[t[f].son[ch]].fa=f;
48 t[u].son[ch^1]=f;
49 t[f].fa=u;
50 t[u].fa=ff;
51 pushup(f);
52 pushup(u);
53 }
54 void splay(int u){
55 int now=u;
56 s[top=1]=now;
57 while(ntrt(now))s[++top]=now=t[now].fa;
58 while(top)pd(s[top--]);
59 while(ntrt(u)){
60 int f=t[u].fa,ff=t[f].fa;
61 if(ntrt(f)){
62 rotate(lr(u)==lr(f)?f:u);
63 }
64 rotate(u);
65 }
66 }
67 void access(int u){
68 for(int now=0;u;now=u,u=t[u].fa){
69 splay(u);
70 t[u].sz2+=t[t[u].son[1]].sz1-t[now].sz1;
71 t[u].son[1]=now;
72 pushup(u);
73 }
74 }
75 void makert(int u){
76 access(u);
77 splay(u);
78 getrev(u);
79 }
80 void link(int x,int y){
81 makert(x);
82 makert(y);
83 ans+=(ll)t[x].sz1*t[y].sz1;
84 t[y].fa=x;
85 t[x].sz2+=t[y].sz1;
86 pushup(x);
87 }
88 void cut(int x,int y){
89 makert(x);
90 access(y);
91 splay(y);
92 t[x].fa=t[y].son[0]=0;
93 pushup(y);
94 }
95 int main(){
96 scanf("%d",&n);
97 for(int i=1;i<n;i++){
98 scanf("%d%d%d%d",&u,&v,&l,&r);
99 q[++cnt]=(task){0,u,v,l};
100 q[++cnt]=(task){1,u,v,r};
101 }
102 sort(q+1,q+cnt+1);
103 for(int i=1;i<=cnt;i++){
104 if(!q[i].op)link(q[i].u,q[i].v);
105 else cut(q[i].u,q[i].v);
106 }
107 printf("%lld",ans);
108 return 0;
109 }