列表

详情


NC200326. 世界线

描述

在无数次的改变世界线之后,牛牛终于完成了对世界线变动模型的构建

牛牛的理论认为,所有的世界线可以抽象为n 个点,而在其中转换的契机就是电话烤箱的释放的电量。
具体来说,所有的世界线由 m 条能量线连接而成的不存在环的无向图,由于世界线的不稳定性,能量线随机连接世界线。
经过每一条能量线都需要消耗能量,定义从一个点u到另一个点v之间的至少经过一条能量线的简单路径所消耗总能量为 u 到 v 的世界变动量。
为了更方便的改变世界的支配构造,牛牛想要知道从一个点  x出发到其他点中第 k 大的世界变动量大小。
由于牛牛不屑于计算这些东西,他把这个任务交给了在屏幕外面吃瓜的你

输入描述

第一行为三个数n,m,q 分别表示世界线、能量线以及牛牛询问的数量
之后的2 ~ m+1 行,每行三个整数 u,v,w,表示 u 到 v 之间转换需要的能量
接下来的 q 行,每行两个整数 x,k ,意义见题目描述
其中1<=m<n<=100,000;q<=100,000;w>=1;1<=x<=n
所有数据在int范围内

输出描述

共 q 行,每行一个整数,表示第 k 大的世界变动量大小,如果不存在输出 -1

示例1

输入:

9 8 3
1 2 5
2 3 1
2 4 1
2 5 1
1 6 2
1 7 3
7 8 6
7 9 9
1 1
5 4
9 9

输出:

12
8
-1

说明:

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 4228ms, 内存消耗: 211536K, 提交时间: 2020-06-01 21:39:26

/*
    可以用平衡树搞,
    也可以用线段树二分加动态开点搞.
    好像都很麻烦呢.
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,M=2e7+50;
const ll low=-5e14,up=5e14;
int n,m,q;
int rt,tot;
int siz,sum;
bool vis[N];
int t[M],ls[M],rs[M];
ll ans[N],dis[N],cf[N];
int b[N],head[N],nex[N<<1],to[N<<1],wi[N<<1];
vector<pair<int,int>>v[N];
int newnode() {
	tot++;
	t[tot]=ls[tot]=rs[tot]=0;
	return tot;
}
void add(int u,int v,int w) {
	to[++sum]=v;
	nex[sum]=head[u];
	head[u]=sum;
	wi[sum]=w;
}
void Insert(ll l,ll r,ll x,int &now,int v) {
	if(!now) now=newnode();
	t[now]+=v;
	if(l==r) return;
	ll m=l+r>>1;
	if(x<=m) Insert(l,m,x,ls[now],v);
	else Insert(m+1,r,x,rs[now],v);
}
ll query(ll l,ll r,int k,int &now) {
	if(l==r) return l;
	ll m=l+r>>1;
	if(t[rs[now]]>=k) return query(m+1,r,k,rs[now]);
	return query(l,m,k-t[rs[now]],ls[now]);
}
void dfs1(int u) {
	siz++;
	assert(dis[u]>=low&&dis[u]<=up);
	Insert(low,up,dis[u],rt,1);
	vis[u]=true;
	for(int i=head[u]; i; i=nex[i]) {
		int v=to[i];
		if(vis[v]) continue;
		cf[v]=dis[v]=dis[u]+wi[i];
		dfs1(v);
	}
}
void updata(int u,int p,ll w) {
	Insert(low,up,dis[u],rt,-1);
	dis[u]+=w;
	assert(dis[u]>=low&&dis[u]<=up);
	Insert(low,up,dis[u],rt,1);
	for(int i=head[u]; i; i=nex[i]) {
		int v=to[i];
		if(v==p) continue;
		updata(v,u,w);
	}
}
void dfs2(int u,int p) {
	for(pair<int,int>x:v[u]) {
		if(x.first>=siz) ans[x.second]=-1;
		else ans[x.second]=query(low,up,x.first,rt)+cf[u];
	}
	for(int i=head[u]; i; i=nex[i]) {
		int v=to[i];
		if(v==p) continue;
		updata(v,u,-2ll*wi[i]);
		dfs2(v,u);
		updata(v,u,2ll*wi[i]);
	}
}
void solve(int x) {
	rt=tot=siz=0;
	dfs1(x);
	dfs2(x,0);
}
int main() {
	scanf("%d%d%d",&n,&m,&q);
//	random_shuffle(b+1,b+1+n);
	for(int i=1; i<=m; i++) {
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
	}
	for(int i=1; i<=q; i++) {
		int x,k;
		scanf("%d%d",&x,&k);
		v[x].push_back({k,i});
	}
	for(int i=1; i<=n; i++)
		if(!vis[i]) {
			solve(i);
		}
	for(int i=1; i<=q; i++) printf("%lld\n",ans[i]);
}

C++14(g++5.4) 解法, 执行用时: 4508ms, 内存消耗: 407288K, 提交时间: 2020-04-30 10:43:21

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+10;
const ll low=-1e15,up=1e15;
ll rt,tot,t[N*100],ls[N*100],rs[N*100];
ll newnode(){tot++;t[tot]=ls[tot]=rs[tot]=0;return tot;}
ll ans[N],dis[N],cf[N];
bool vis[N];
ll n,m,q,si,sum,head[N],nex[N<<1],to[N<<1],wi[N<<1];
void add(ll u,ll v,ll w){to[++sum]=v;nex[sum]=head[u];head[u]=sum;wi[sum]=w;}
vector<pair<ll,ll>>v[N];
void Insert(ll l,ll r,ll x,ll &now,ll v)
{
    if(!now) now=newnode();
    t[now]+=v;
    if(l==r) return;
    ll m=l+r>>1;
    if(x<=m) Insert(l,m,x,ls[now],v);
    else Insert(m+1,r,x,rs[now],v);
}
ll query(ll l,ll r,ll k,ll &now)
{
    if(l==r) return l;
    ll m=l+r>>1;
    if(t[rs[now]]>=k) return query(m+1,r,k,rs[now]);
    return query(l,m,k-t[rs[now]],ls[now]);
}
void dfs(ll u)
{
    si++;
    Insert(low,up,dis[u],rt,1);
    vis[u]=true;
    for(ll i=head[u];i;i=nex[i])
    {
        ll v=to[i];if(vis[v])continue;
        cf[v]=dis[v]=dis[u]+wi[i];
        dfs(v);
    }
}
void vvv(ll u,ll p,ll w)
{
    Insert(low,up,dis[u],rt,-1);
    dis[u]+=w;
    Insert(low,up,dis[u],rt,1);
    for(ll i=head[u];i;i=nex[i])
    {
        ll v=to[i];if(v==p) continue;
        vvv(v,u,w);
    }
}
void dfs(ll u,ll p)
{
    for(pair<ll,ll>x:v[u])
    {
        if(x.first>=si) ans[x.second]=-1;
        else ans[x.second]=query(low,up,x.first,rt)+cf[u];
    }
    for(ll i=head[u];i;i=nex[i])
    {
        ll v=to[i];if(v==p) continue;
        vvv(v,u,-2ll*wi[i]);
        dfs(v,u);
        vvv(v,u,2ll*wi[i]);
    }
}
void solve(ll x)
{
    rt=tot=si=0;
    dfs(x);
    dfs(x,0);
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&q);
    for(ll i=1;i<=m;i++)
    {
        ll u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);add(v,u,w);
    }
    for(ll i=1;i<=q;i++)
    {
        ll x,k;scanf("%lld%lld",&x,&k);
        v[x].push_back({k,i});
    }
    for(ll i=1;i<=n;i++)
        if(!vis[i])
    {
        solve(i);
    }
    for(ll i=1;i<=q;i++) printf("%lld\n",ans[i]);
    return 0;
}

上一题