用树剖的全re,吸了氧全ac
查看原帖
用树剖的全re,吸了氧全ac
403799
Butane楼主2022/1/21 23:15

用树剖的全re,吸了氧全ac,有无好心大佬解释一下为何如此?

#include <stdio.h>
#include <iomanip>
#include <vector>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <map>
#include <time.h>
#include <queue>
#include <iostream>
#include <cstring>
#include <set>
using namespace std;

const int maxv=1e5+10;
const int mod=1e9+7;
const int maxNum=0x7fffffff-10;
const double eps=1e-8;
const double PI=3.1415926535;
typedef long long LL;

inline LL read(){
     LL x=0,f=1;
     char ch=getchar();
     while(ch<'0'||ch>'9'){
         if(ch=='-')
             f=-1;
         ch=getchar();
     }
     while(ch>='0'&&ch<='9'){
         x=(x<<1)+(x<<3)+(ch^48);
         x%=mod;
         ch=getchar();
     }
     return x*f;
}
inline void write(int x)
 {
    if(!x) putchar('0');
    char F[200];
    int tmp=x>0?x:-x ;
    if(x<0)putchar('-') ;
    int cnt=0 ;
    while(tmp>0)
    {
       F[cnt++]=tmp%10+'0';
       tmp/=10;
    }
    while(cnt>0)putchar(F[--cnt]) ;
    putchar('\n');
}

#define int long long
int n,m,r,p;
const int N =maxv;
struct E{ int v ;int nxt ; } ;
E edge[N << 1] ;
int a[N],fa[N],w[N],id[N],son[N] ;
int cnt,head[N],Add[N<<2],laz[N<<2],dep[N],siz[N],t[N] ;
inline void Add_Edge( int u ,  int v) { edge[++ cnt].v = v ; edge[cnt].nxt = head[u] ; head[u] = cnt ; return ; }//建边。
#define l(x) x << 1
#define r(x) x << 1 | 1
inline void Push_down( int x ,  int len) {
    laz[l(x)] += laz[x] ; laz[r(x)] += laz[x] ;
    Add[l(x)] += laz[x] * (len - (len >> 1)) ; Add[r(x)] += laz[x] * (len >> 1) ;
    Add[l(x)] %= p ; Add[r(x)] %= p ;
    laz[x] = 0 ; return ;
}
inline void Build( int l ,  int r ,  int rt) {//建树
    if(l == r) { Add[rt] = a[l] ;  return ; }
     int mid = l + r >> 1 ;
    Build(l , mid , l(rt)) ; Build(mid + 1 , r , r(rt)) ;
    Add[rt] = (Add[l(rt)] + Add[r(rt)]) % p ;
}
inline void Update( int a ,  int b ,  int l  ,  int r ,  int rt ,  int k) {//正常的线段树操作
    if(a <= l and r <= b) { laz[rt] += k ; Add[rt] += k * (r - l + 1) ; }
    else {
        if(laz[rt]) Push_down(rt , r - l + 1) ;
         int mid = l + r >> 1 ;
        if(a <= mid) Update(a , b , l , mid , l(rt) , k) ;
        if(b > mid) Update(a , b , mid + 1 , r , r(rt) , k) ;
        Add[rt] = (Add[l(rt)] + Add[r(rt)]) % p ;
    }
}
int res = 0 ;
inline void query( int a ,  int b ,  int  l ,  int r ,  int rt) {
    if(a <= l and r <= b) { res = (res + Add[rt]) % p ; return ; }
    else {
        if(laz[rt]) Push_down(rt , r - l + 1) ;
         int mid = l + r >> 1 ;
        if(a <= mid) query(a , b , l , mid , l(rt)) ;
        if(b > mid) query(a , b , mid + 1 , r , r(rt)) ;
    }
}
inline int Query( int a ,  int b ,  int l ,  int r ,  int rt) {//正常的线段树操作
    res = 0 ; query(a , b , l , r , rt) ;
    return res % p ;
}
inline void Upd_Range( int x ,  int y ,  int k) {//链上修改
    while(t[x] != t[y]) {
        if(dep[t[x]] < dep[t[y]]) swap(x , y) ;
         Update(id[t[x]] , id[x] , 1 , n , 1 , k) ;
         x = fa[t[x]] ;
    }
    if(dep[x] > dep[y]) swap(x , y) ;
    Update(id[x] , id[y] , 1 , n , 1 , k) ;
}
inline int Query_Range( int x ,  int y) {//链上查询
    int ans = 0 ;
    while(t[x] != t[y]) {
        if(dep[t[x]] < dep[t[y]]) swap(x , y) ;
        ans += Query(id[t[x]] , id[x] , 1 , n , 1) ;
        x = fa[t[x]] ;
    }
    if(dep[x] > dep[y]) swap(x , y) ;
    ans += Query(id[x] , id[y] , 1 , n , 1) ;
    return ans % p ;
}
inline int Qson( int x) { return Query(id[x] , id[x] + siz[x] - 1 , 1 , n , 1) ; } // 子树查询。
inline void Updson( int x ,  int k) { Update(id[x] , id[x] + siz[x] - 1 , 1 , n , 1 , k) ; return ; }
inline void Dfs1( int x ,  int f ,  int deep) {
    dep[x] = deep ; fa[x] = f ; siz[x] = 1 ;
    int max_son = -1 ;
    for( int i = head[x] ; i ; i = edge[i].nxt) {
         int v = edge[i].v ;
        if(v == f) continue ;
        Dfs1(v , x , deep + 1) ;siz[x] += siz[v] ;
        if(siz[v] > max_son) max_son = siz[v] , son[x] = v ;
    }
}
int tot = 0 ;
inline void Dfs2( int x ,  int tf) {
    id[x] = ++ tot ; a[tot] = w[x] ; t[x] = tf ; // a 数组重新赋值
    if(! son[x]) return ;
    Dfs2(son[x] , tf) ;
    for( int i = head[x] ; i ; i = edge[i].nxt) {
        int v = edge[i].v ;
        if(v == fa[x] or v == son[x]) continue ;
        Dfs2(v , v) ;
    }
}
signed main() {
    n = read() ; m = read() ; r = 1; p = 2e9 ;
    for(int i = 1 ; i <= n ; i ++) w[i] = 0;
    for(int i = 1 ; i <= n - 1 ; i ++) {
        int u = read() , v = read() ;
        Add_Edge(u , v) ;
        Add_Edge(v , u) ;
    }
    Dfs1(r , 0 , 1) ; Dfs2(r , r) ; Build(1 , n , 1) ;
    while(m--){
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        Upd_Range(a , b , 1) ;
        if(Query_Range(c , d)>0) printf("Y\n");
        else printf("N\n");
        Upd_Range(a , b , -1) ;
    }
    return 0 ;
}

2022/1/21 23:15
加载中...