11.03T2 树链剖分

5956 -- 【模拟试题】相交

Description

给你一棵树,每次询问树上两条链是否有交点。

Input

第一行n,表示n个结点
第二行开始n-1行俩个·数x y,表示x,y有一条边
接下来q,表示q个询问
接下来q行四个数a b c d,询问a到b的链是否与c到d的链有交点

Output

输出Q行(YES或NO)

Sample Input

输入1:

8

1 2

1 3

2 4

2 5

5 6

5 7

3 8

4

2 5 4 3

5 3 8 8

5 4 6 7

4 8 6 7

输入2:

15

2 1

3 1

4 2

5 3

6 2

7 2

8 5

9 3

10 6

11 5

12 7

13 11

14 1

15 1

5

1 2 3 4

4 7 1 9

2 3 7 9

2 6 7 8

2 1 6 8

Sample Output

输出1:

YES

NO

YES

NO

输出2:

YES

NO

YES

YES

YES

 

Hint

30%的数据1≤n,q≤3000
另外20%数据是一条链
100%的数据1≤n,q≤100000
 
 

题意:给你一棵树,每次询问树上两条链是否有交点。

 30% 将第一条链上所有点打上标记,再遍历第二条链,查看第二条链上是 否有打上标记的点。

另外 20% 树退化为一条链,每次询问等价于查询数轴上两条线段是否相交。 100% 仔细观察不难发现,两条树链相交的充要条件是其中一条路径的顶点 在另一条路径上,每次询问求出 lca 判断即可。

管他什么正解,直接上树链剖分
code:
  1 #include<iostream>
  2 #include<cstdio>
  3 #define N 1000006
  4 #define lc (p<<1)
  5 #define rc (p<<1|1) 
  6 using namespace std;
  7 struct node{
  8     int u,v;
  9 }e[N];
 10 int first[N],nxt[N],cnt;
 11 void add(int u,int v){
 12     e[++cnt].u=u;
 13     e[cnt].v=v;
 14     nxt[cnt]=first[u];
 15     first[u]=cnt;
 16 }
 17 struct T{
 18     int l,r,sum,lazy;
 19 }t[N];
 20 void pushup(int p){
 21     t[p].sum=t[lc].sum+t[rc].sum;
 22 }
 23 void pushnow(int p,int v){
 24     t[p].sum+=(t[p].r-t[p].l+1)*v;
 25     t[p].lazy+=v;
 26 }
 27 void pushdown(int p){
 28     if(t[p].lazy){
 29         pushnow(lc,t[p].lazy);
 30         pushnow(rc,t[p].lazy);
 31         t[p].lazy=0;
 32     }
 33 }
 34 void build(int p,int l,int r){
 35     t[p].l=l,t[p].r=r;
 36     if(l==r){
 37         t[p].sum=0;
 38         t[p].lazy=0;
 39         return;
 40     }
 41     int mid=l+r>>1;
 42     build(lc,l,mid);
 43     build(rc,mid+1,r);
 44     pushup(p);
 45 }
 46 void update(int p,int ql,int qr,int v){
 47     if(ql<=t[p].l&&t[p].r<=qr){
 48         pushnow(p,v);
 49         return;
 50     }
 51     pushdown(p);
 52     int mid=t[p].l+t[p].r>>1;
 53     if(ql<=mid)update(lc,ql,qr,v);
 54     if(qr>mid)update(rc,ql,qr,v);
 55     pushup(p);
 56 }
 57 int query(int p,int ql,int qr){
 58     if(ql<=t[p].l&&t[p].r<=qr){
 59         return t[p].sum;
 60     }
 61     int ans=0;
 62     pushdown(p);
 63     int mid=t[p].l+t[p].r>>1;
 64     if(ql<=mid)ans+=query(lc,ql,qr);
 65     if(qr>mid)ans+=query(rc,ql,qr);
 66     pushup(p);
 67     return ans;
 68 }
 69 int siz[N],hson[N],fa[N],dep[N];
 70 void dfs1(int x){
 71     siz[x]=1;
 72     hson[x]=0;
 73     for(int i=first[x];i;i=nxt[i]){
 74         int v=e[i].v;
 75         if(v==fa[x])continue;
 76         fa[v]=x;
 77         dep[v]=dep[x]+1;
 78         dfs1(v);
 79         siz[x]+=siz[v];
 80         if(!hson[x]||siz[hson[x]]<siz[v])hson[x]=v;
 81     }
 82 }
 83 int top[N],num[N],pre[N],tot;
 84 void dfs2(int x,int tp){
 85     top[x]=tp;
 86     num[x]=++tot;
 87     pre[tot]=x;
 88     if(hson[x])dfs2(hson[x],tp);
 89     for(int i=first[x];i;i=nxt[i]){
 90         int v=e[i].v;
 91         if(v==fa[x]||v==hson[x])continue;
 92         dfs2(v,v);
 93     }
 94 }
 95 void modify(int x,int y,int v){
 96     while(top[x]!=top[y]){
 97         if(dep[top[x]]<dep[top[y]])swap(x,y);
 98         update(1,num[top[x]],num[x],v);
 99         x=fa[top[x]];
100     }
101     if(dep[x]<dep[y])swap(x,y);
102     update(1,num[y],num[x],v);
103 }
104 int ask_sum(int x,int y){
105     int ans=0;
106     while(top[x]!=top[y]){
107         if(dep[top[x]]<dep[top[y]])swap(x,y);
108         ans+=query(1,num[top[x]],num[x]);
109         x=fa[top[x]];
110     }
111     if(dep[x]<dep[y])swap(x,y);
112     ans+=query(1,num[y],num[x]);
113     return ans;
114 }    
115 int read(){
116     int x=0,f=1;
117     char c=getchar();
118     while(!isdigit(c)){
119         if(c=='-')f=-1;
120         c=getchar();
121     }
122     while(isdigit(c)){
123         x=(x<<1)+(x<<3)+c-'0';
124         c=getchar();
125     }
126     return x*f;
127 }
128 int main(){
129     int n;
130     n=read();
131     for(int i=1;i<n;i++){
132         int u,v;
133         u=read(),v=read();
134         add(u,v);
135         add(v,u);
136     }
137     dfs1(1);
138     dfs2(1,1);
139     build(1,1,n);
140     int m;
141     m=read();
142     for(int i=1;i<=m;i++){
143         int a,b,c,d;
144         a=read(),b=read(),c=read(),d=read();
145         modify(a,b,1);
146         if(ask_sum(c,d))cout<<"YES"<<'
';
147         else cout<<"NO"<<'
';
148         modify(a,b,-1);
149     }
150 }
151 //调试语句注意  

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9902347.html