Portal
Implication: Give an undirected graph, each edge has a size interval [l,r], representing the number of schemes that can be calculated from 1 to n by human size.
Solution: It can be done by lct, but I haven't learned LCT yet. In the method of line segment tree + union search, we first discretize the size, so that the nodes of line segment tree represent a section of size interval, all left open and right closed (so that it can be handled). Then we add the edges that conform to the nodes, without dropping them down. Finally, we searched deeply, searched deeply at the same time the edges of the node, and used and collected the connectivity between the maintenance points. When we found the leaf nodes, it showed that the edges covering the interval had been added to judge the connectivity between 1 and n. If connected, the values in the interval representing this size could make 1 to n, plus contributions. In retrospect, we can cancel the added edge.
#include<bits/stdc++.h> #define il inline #define pb push_back #define ms(_data,v) memset(_data,v,sizeof(_data)) #define SZ(a) int((a).size()) using namespace std; typedef long long ll; const ll inf=0x3f3f3f3f; const double pi=acos(-1.0); const int maxn=1e5+5; //il int Add(int x,int y) {return x+y>=mod?x+y-mod:x+y;} //il int Mul(ll x,int y) {return x*y>=mod?x*y%mod:x*y;} int s[maxn<<2],n,m,ans=0; vector<int> un[maxn<<3][2]; struct Collect{ int fa[maxn],rk[maxn]; void init(){ for(int i=0;i<maxn;++i) fa[i]=i,rk[i]=0; } int search(int x){ while(x^fa[x]) x=fa[x]; return x; } void unite(int x,int y,int rt){ x=search(x),y=search(y); if(x==y) return ; if(rk[x]>rk[y]){ fa[y]=x; un[rt][1].pb(x),un[rt][0].pb(y); //father and son } else{ fa[x]=y; if(rk[x]==rk[y]) rk[y]++; un[rt][1].pb(y),un[rt][0].pb(x); } } void reunite(int rt){ int len=SZ(un[rt][1]); for(int i=0;i<len;++i){ rk[un[rt][1][i]]-=rk[un[rt][0][i]]; fa[un[rt][0][i]]=un[rt][0][i]; } un[rt][1].clear(),un[rt][0].clear(); } }co; struct Tree { struct node { int l,r; bool fg; vector<int> v; } sum[maxn<<3]; void build(int l,int r,int rt) { if(l==r) { sum[rt].fg=1; sum[rt].l=s[l],sum[rt].r=s[l+1]; return ; } int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); sum[rt].l=sum[rt<<1].l,sum[rt].r=sum[rt<<1|1].r; } void update(int L,int R,int rt,int u,int v) { if(L<=sum[rt].l && R>=sum[rt].r){ sum[rt].v.pb(u); sum[rt].v.pb(v); return ; } if(L<sum[rt<<1].r) update(L,R,rt<<1,u,v); if(R>sum[rt<<1|1].l) update(L,R,rt<<1|1,u,v); } void over(int rt){ if(SZ(sum[rt].v)){ int len=SZ(sum[rt].v); for(int i=0;i<len;i+=2){ co.unite(sum[rt].v[i],sum[rt].v[i+1],rt); } } if(sum[rt].fg){ if(co.search(1)==co.search(n)){ ans+=sum[rt].r-sum[rt].l; } return ; } over(rt<<1); co.reunite(rt<<1); over(rt<<1|1); co.reunite(rt<<1|1); } }tree; int U[maxn],V[maxn],L[maxn],R[maxn]; int main() { std::ios::sync_with_stdio(0); scanf("%d%d",&n,&m); int tot=0; for(int i=1; i<=m; ++i) { scanf("%d%d%d%d",&U[i],&V[i],&L[i],&R[i]); s[++tot]=L[i],s[++tot]=(++R[i]); } sort(s+1,s+tot+1); tot=unique(s+1,s+tot+1)-(s+1); tree.build(1,tot-1,1); co.init(); for(int i=1;i<=m;++i){ tree.update(L[i],R[i],1,U[i],V[i]); } tree.over(1); printf("%d\n",ans); return 0; }