Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define sws ios_base::sync_with_stdio(false); cin.tie(nullptr);cout.tie(nullptr);
- #define ld long double
- #define ff first
- #define ss second
- #define dbg(x) cout<<#x<<": "<<x<<"\n";
- #define pq priority_queue
- #define mp make_pair
- #define pb push_back
- #define rep(i,a,b) for(int i=a;i<b;i++)
- typedef vector<int> vi;
- typedef vector<vi> vvi;
- typedef pair<int,int>pii;
- const int MAXN = 1e5+1;
- vi adj[MAXN];
- int head[MAXN];
- int heavy_c[MAXN];
- int idx[MAXN];
- int fat[MAXN];
- int h[MAXN];
- int tt=0;
- int dfs1(int v=1 ,int p=1,int he=0){
- pii m = mp(0,v);
- fat[v]=p;
- h[v]=he;
- for(auto c:adj[v]){
- if(c==p)continue;
- pii mm = mp(dfs1(c,v,he+1),c);
- mm.ff++;
- m = max(mm,m);
- }
- heavy_c[v]=m.ss;
- return m.ff;
- }
- void dfs2(int v=1,int p=-1,int curhead=1){
- idx[v]=tt++;
- head[v]=curhead;
- if(heavy_c[v]!=v)dfs2(heavy_c[v],v,curhead);
- for(auto c:adj[v]){
- if(c==p || c==heavy_c[v])continue;
- dfs2(c,v,c);
- }
- }
- struct SegTree{
- vi lazy;
- vi t;
- int n;
- SegTree(int n):n(n),lazy(n<<2,0),t(n<<2,0){}
- void push(int v,int tl,int tr){
- if(lazy[v]==0)return;
- int tm = (tl+tr)/2;
- int szl = tm-tl+1;
- int szr = tr-tm;
- t[v<<1]+=(szl*lazy[v]);
- t[v<<1|1]+=(szr*lazy[v]);
- lazy[v<<1]+=lazy[v];
- lazy[v<<1|1]+=lazy[v];
- lazy[v]=0;
- }
- void update(int v,int tl,int tr,int l,int r,int val){
- if(tl==l && tr==r){
- t[v]+=(tr-tl+1)*val;
- lazy[v]+=val;
- return;
- }
- if(tl>r ||tr<l)return;
- push(v,tl,tr);
- int tm = (tl+tr)/2;
- update(v<<1,tl,tm,l,min(tm,r),val);
- update(v<<1|1,tm+1,tr,max(tm+1,l),r,val);
- t[v]=t[v<<1]+t[v<<1|1];
- }
- void update(int l,int r,int val){
- update(1,0,n-1,l,r,val);
- }
- int get(int v,int tl,int tr,int l,int r){
- if(tl==l && tr==r)return t[v];
- if(tl>r ||tr<l)return 0 ;
- push(v,tl,tr);
- int tm = (tl+tr)/2;
- return get(v<<1,tl,tm,l,min(tm,r))+get(v<<1|1,tm+1,tr,max(tm+1,l),r);
- }
- int get(int l,int r){
- return get(1,0,n-1,l,r);
- }
- };
- SegTree st(MAXN);
- void update(int a,int b){
- // cout<<"UPDATE MASTER ENTRE "<<a<<" e "<<b<<"\n";
- while(head[a]!=head[b]){
- if(h[head[a]]<h[head[b]])swap(a,b);
- st.update(idx[head[a]],idx[a],1);
- a=fat[head[a]];
- }
- if(idx[a]>idx[b])swap(a,b);
- st.update(idx[a],idx[b],1);
- }
- int get(int a,int b){
- int ans=0;
- while(head[a]!=head[b]){
- if(h[head[a]]<h[head[b]])swap(a,b);
- ans+=st.get(idx[head[a]],idx[a]);
- a=fat[head[a]];
- }
- if(idx[a]>idx[b])swap(a,b);
- ans+= st.get(idx[a],idx[b]);
- return ans;
- }
- signed main() {
- sws;
- int n,q;
- cin>>n>>q;
- rep(i,0,n-1){
- int a,b;
- cin>>a>>b;
- adj[a].pb(b);
- adj[b].pb(a);
- }
- dfs1();
- dfs2();
- while(q--){
- int a,b,c,d;
- cin>>a>>b>>c>>d;
- int prior = get(c,d);
- update(a,b);
- cout<<get(c,d)-prior<<"\n";
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment