题目链接:点击查看
题意:给出一个树和边权,求节点到根节点路径上的比y小的最大的
题解:本来写了个主席树,超内存了,然后改写树链剖分+线段树,但这样需要离线处理,从小到大来进行,然后就过了,看了之前的代码,感觉主席树不会超内存啊,果断把vector换掉了,就不超了,真是垃圾,以后不会再用vector记录图了,不超时就T了,之前我是二分的答案,然后就T了,细想发现没必要,我们把主席树保存的val值,都记录成该区间内,存在数的最右端的位置,这样只扫一遍就可以了,晚上脑子真是不好用.....
第二天突然想到,既然查询的店都是到节点1的路径上的,那么我们dfs一次就行了,离线操作一下,到哪个点处理哪个,注意要用multiset,删除的时候要按位置删除一个。
树链剖分:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,q;
vector<pair<int,int> >v[N];
struct node{
int l,r;
int val;
}tree[N<<2];
struct node1{
int x,y,z;
bool operator<(const node1 &xx)const
{
return z<xx.z;
}
}e[N];
int len;
struct node2{
int x,y;
int id;
bool operator<(const node2 &xx)const
{
return y<xx.y;
}
}a[N];
int son[N],s_num[N];
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
if(l==r)return;
int mid=(r+l)>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
}
void dfs1(int u,int fa)
{
s_num[u]=1;
int to;
int maxx=-1;
for(int i=0;i<v[u].size();i++)
{
to=v[u][i].first;if(to==fa) continue;
dfs1(to,u);
e[++len].x=u;e[len].y=to;e[len].z=v[u][i].second;
s_num[u]+=s_num[to];
if(s_num[to]>maxx)
{
son[u]=to;
maxx=s_num[to];
}
}
}
int in[N],cnt,f[N],dep[N],faa[N];
void dfs2(int u,int fa,int rt,int deep)
{
in[u]=++cnt;
f[u]=rt;
dep[u]=deep;
faa[u]=fa;
if(son[u]!=-1)
{
dfs2(son[u],u,rt,deep+1);
}
int to;
for(int i=0;i<v[u].size();i++)
{
to=v[u][i].first;if(to==fa || to==son[u]) continue;
dfs2(to,u,to,deep+1);
}
}
void pushup(int cur)
{
tree[cur].val=max(tree[cur<<1].val,tree[cur<<1|1].val);
}
void update(int pos,int cur,int val)
{
if(tree[cur].l==tree[cur].r)
{
tree[cur].val=val;
return;
}
if(pos<=tree[cur<<1].r) update(pos,cur<<1,val);
else update(pos,cur<<1|1,val);
pushup(cur);
}
int query(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
int res=0;
if(pl<=tree[cur<<1].r) res=max(res,query(pl,pr,cur<<1));
if(pr>=tree[cur<<1|1].l) res=max(res,query(pl,pr,cur<<1|1));
return res;
}
int ans[N];
int solve(int x,int y)
{
int f1=f[x],f2=f[y];
int maxx=0;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(x,y);
}
maxx=max(maxx,query(in[f1],in[x],1));
x=faa[x];
f1=f[x];
}
if(dep[x]>dep[y]) swap(x,y);
if(x!=y) maxx=max(maxx,query(in[x]+1,in[y],1));
return maxx;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
cnt=len=0;
for(int i=1;i<=n;i++) v[i].clear(),son[i]=-1;
build(1,n,1);
int x,y,z;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
v[x].push_back(make_pair(y,z));
v[y].push_back(make_pair(x,z));
}
dfs1(1,0);
dfs2(1,0,1,1);
scanf("%d",&q);
for(int i=1;i<=q;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
sort(e+1,e+n);
sort(a+1,a+1+q);
for(int i=1,j=1;i<=q;i++)
{
// cout<<a[i].y<<" ";
while(j<n&&e[j].z<=a[i].y)
{
// cout<<e[j].z<<" ";
update(in[e[j].y],1,e[j].z);
j++;
}
// cout<<j<<endl;
ans[a[i].id]=solve(1,a[i].x);
}
for(int i=1;i<=q;i++)
{
if(ans[i]==0) ans[i]=-1;
printf("%d\n",ans[i]);
}
}
return 0;
}
主席树:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct edge{
int to,nex,d;
}e[N*2];
int head[N],tot;
void addedge(int x,int y,int z)
{
e[tot].to=y;
e[tot].d=z;
e[tot].nex=head[x];
head[x]=tot++;
}
struct node{
int l,r;
int val;
}tree[N*22];
int a[N];
int root[N],cnt;
int len;
int update(int pre,int l,int r,int val)
{
int cur=++cnt;
tree[cur]=tree[pre];
tree[cur].val=max(val,tree[cur].val);
if(l==r) return cur;
int mid=(r+l)>>1;
if(val<=mid) tree[cur].l=update(tree[pre].l,l,mid,val);
else tree[cur].r=update(tree[pre].r,mid+1,r,val);
return cur;
}
void dfs(int u,int fa)
{
int pos,to,val;
for(int i=head[u];i!=-1;i=e[i].nex)
{
to=e[i].to;
if(to==fa)continue;
val=e[i].d;
pos=lower_bound(a+1,a+1+len,val)-a;
root[to]=update(root[u],1,len,pos);
dfs(to,u);
}
}
int query(int pl,int pr,int l,int r,int x)
{
if(pl<=l&&r<=pr)
{
// cout<<l<<" "<<r<<" "<<tree[x].val<<endl;
return tree[x].val;
}
int mid=(r+l)>>1;
int res=0;
if(pl<=mid) res=max(res,query(pl,pr,l,mid,tree[x].l));
if(pr>mid) res=max(res,query(pl,pr,mid+1,r,tree[x].r));
return res;
}
int n,q;
struct node1{
int x,y;
}b[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cnt=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)head[i]=-1;
tot=0;
int x,y,z;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
a[i]=z;
addedge(x,y,z);
addedge(y,x,z);
}
sort(a+1,a+n);
len=unique(a+1,a+n)-(a+1);
// cout<<len<<endl;
dfs(1,0);
int pos;
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
pos=lower_bound(a+1,a+1+len,y)-a;
if(pos>len||a[pos]!=y) pos--;
if(pos==0) printf("-1\n");
else
{
int ans=query(1,pos,1,len,root[x]);
if(ans==0) printf("-1\n");
else
printf("%d\n",a[ans]);
}
}
}
return 0;
}
/*
2
3
1 2 7
2 3 5
4
3 10
3 7
3 6
3 4
7
1 2 1
1 3 2
2 4 3
2 5 4
3 6 5
3 7 6
10
*/
multiset:
#include<bits/stdc++.h>
using namespace std;
#define mk make_pair
#define pb push_back
const int N=1e5+10;
struct edge{
int to,nex,val;
}e[N*2];
int n,q;
int head[N],len;
vector<pair<int,int> > v[N];
multiset<int> s;
multiset<int>::iterator it;
int ans[N];
void init()
{
len=0;
for(int i=1;i<=n;i++)
{
head[i]=-1;
v[i].clear();
}
}
void addedge(int x,int y,int z)
{
e[len].to=y;
e[len].val=z;
e[len].nex=head[x];
head[x]=len++;
}
void dfs(int u,int fa)
{
int to,val;
int cnt=v[u].size(),id;
for(int i=0;i<cnt;i++)
{
val=v[u][i].first;
id=v[u][i].second;
it=s.upper_bound(val);
if(it==s.begin())ans[id]=-1;
else
{
it--;
ans[id]=*it;
}
}
for(int i=head[u];~i;i=e[i].nex)
{
to=e[i].to;if(to==fa)continue;
val=e[i].val;
s.insert(val);
dfs(to,u);
it=s.lower_bound(val);
s.erase(it);
}
}
int main()
{
int T;
int x,y,z;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
v[x].pb(mk(y,i));
}
dfs(1,0);
for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
}
return 0;
}