BZOJ 3251: 树上三角形
作者:互联网
题解:
这是一个判定性问题。
>47个点就必定有解。可以通过较小两边之和<=第三边来证明。
然后就暴力往上跳存下来暴力判断就行了。
树剖AC Code:
#include<bits/stdc++.h>
#define maxn 400005
#define pb push_back
#define lc u<<1
#define rc u<<1|1
#define lim 55
using namespace std;
int n,q;
int ar[maxn][lim],a[maxn];
vector<int>G[maxn];
int dep[maxn],tp[maxn],fa[maxn],siz[maxn],son[maxn],id[maxn],pos[maxn],tot;
void dfs(int u,int ff){
dep[u] = dep[fa[u] = ff] + (siz[u] = 1);
for(int i=0,v;i<G[u].size();i++)
if((v=G[u][i]) != ff){
dfs(v,u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])
son[u] = v;
}
}
void dfs2(int u,int ff){
pos[id[u] = ++tot] = u;
if(son[u]) tp[son[u]] = tp[u] , dfs2(son[u] , u);
for(int i=0,v;i<G[u].size();i++)
if((v=G[u][i]) != ff && v!=son[u]){
tp[v] = v,dfs2(v,u);
}
}
int tmp[lim];
void merge(int *a,int *b,int *c){
int i = 0 , j = 0 , k = 0;
memset(tmp,-0x3f,sizeof tmp);
for(;i<lim && j<lim && k<lim && (a[i]>0 || b[j]>0);)
if(a[i] < b[j]) tmp[k++] = b[j++];
else tmp[k++] = a[i++];
for(i=0;i<lim;i++)
c[i] = tmp[i];
}
void upd(const int &u){
merge(ar[lc],ar[rc],ar[u]);
}
void Build(int u,int l,int r){
if(l == r){
ar[u][0] = a[pos[l]];
return;
}
int mid = (l+r) >> 1;
Build(lc,l,mid),Build(rc,mid+1,r);
upd(u);
}
void Insert(int u,int l,int r,int pos,int v){
if(l == r){
ar[u][0] = v;
return;
}
int mid = (l+r) >> 1;
if(pos <= mid) Insert(lc,l,mid,pos,v);
else Insert(rc,mid+1,r,pos,v);
upd(u);
}
void Query(int u,int l,int r,int ql,int qr,int *c){
if(ql > r || l > qr) return;
if(ql <= l && r <= qr){
merge(c,ar[u],c);
return;
}
int mid = (l+r) >> 1;
Query(lc,l,mid,ql,qr,c),Query(rc,mid+1,r,ql,qr,c);
}
int rt[60];
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int a,b;scanf("%d%d",&a,&b);
G[a].pb(b),G[b].pb(a);
}
dfs(1,0),tp[1]=1,dfs2(1,0);
memset(ar,-0x3f,sizeof ar);
Build(1,1,n);
for(int t,a,b;q--;){
scanf("%d%d%d",&t,&a,&b);
if(t == 0){
memset(rt,-0x3f,sizeof rt);
for(;tp[a]!=tp[b];){
if(dep[tp[a]] < dep[tp[b]]) swap(a,b);
Query(1,1,n,id[tp[a]],id[a],rt);
a = fa[tp[a]];
}
Query(1,1,n,min(id[a],id[b]),max(id[a],id[b]),rt);
bool flg = 0;
for(int i=0;i+2<lim && rt[i+2] > 0;i++)
if(1ll * rt[i+2] + 1ll * rt[i+1] > rt[i]){
flg = 1;
break;
}
if(flg)
puts("Y");
else
puts("N");
}
else{
Insert(1,1,n,id[a],b);
}
}
}
标签:pos,int,3251,mid,son,++,maxn,三角形,BZOJ 来源: https://blog.csdn.net/qq_35950004/article/details/100830080