제출 #979046

#제출 시각아이디문제언어결과실행 시간메모리
979046temporary1Two Currencies (JOI23_currencies)C++14
100 / 100
2950 ms207420 KiB
#include <bits/stdc++.h>
using namespace std;

#define f first
#define s second

struct node {
	long long val;
	int cnt;
	node *left, *right;
	node(long long val, int cnt, node* left, node *right) : val(val), cnt(cnt), left(left), right(right) {};
};
node *perstree[100001];
int in[100001];
int out[100001];
int height[100001];
int bl[100001][20];
pair<int,int> edges[100001];
vector<pair<int,int>> graph[100001];
vector<pair<int,int>> vctr;
int n;
int total[100001];
int borders[100001];

long long getval(node *n) {
	if (n)return n->val;
	else return 0;
}

int getcnt(node *n) {
	if (n)return n->cnt;
	else return 0;
}

node* build(int a, int b) {
	if (a > b)return NULL;
	if (a == b) {
		return new node(0,0,NULL,NULL);
	}
	return new node(0,0,build(a,(a+b)/2),build((a+b)/2+1,b));
}

node* update(node *n, int a, int b, int x, long long v, int c) {
	// printf("%d %d %d %lld\n",a,b,x,v);
	if (a > b)return NULL;
	if (a == b) {
		// printf("%d : %lld + %lld , %d + %d\n",a,n->val,v,n->cnt,c);
		return new node(n->val+v,n->cnt+c,NULL,NULL);
	}
	node* nleft;
	node* nright;
	if (x <= (a+b)/2) {
		nleft = update(n->left,a,(a+b)/2,x,v,c);
		nright = n->right;
	} else if (x >= (a+b)/2+1) {
		nright = update(n->right,(a+b)/2+1,b,x,v,c);
		nleft = n->left;
	}
	// printf("%d-%d : %lld -> %lld , %d -> %d\n",a,b,n->val,getval(nleft)+getval(nright),n->cnt,getcnt(nleft)+getcnt(nright));
	return new node(getval(nleft)+getval(nright),getcnt(nleft)+getcnt(nright),nleft,nright);
}

pair<long long,int> query(node *n, int a, int b, int x, int y) {
	if (a > b || b < x || y < a)return {0,0};
	if (x <= a && b <= y) {
		// printf("%d=%d : %lld , %d\n",a,b,n->val,n->cnt);
		return {n->val,n->cnt};
	}
	pair<long long,int> qleft, qright;
	if (y <= (a+b)/2) {
		qleft = query(n->left,a,(a+b)/2,x,y);
		qright = {0,0};
	} else if (x >= (a+b)/2+1) {
		qright = query(n->right,(a+b)/2+1,b,x,y);
		qleft = {0,0};
	} else {
		qleft = query(n->left,a,(a+b)/2,x,y);
		qright = query(n->right,(a+b)/2+1,b,x,y);
	}
	// printf("%d==%d %d %d: %lld , %d\n",a,b,x,y,qleft.f+qright.f,qleft.s+qright.s);
	return {qleft.f+qright.f,qleft.s+qright.s};
}

void findsize(int node, int pa, int h) {
	height[node] = h;
	if (pa != -1) {
		bl[node][0] = pa;
	}
	if (pa != -1)bl[node][0] = pa;
	for (auto it : graph[node]) {
		if (it.f == pa)continue;
		findsize(it.f,node,h+1);
	}
	return;
}

void findborders(int node, int pa, int b) {
	total[node] = b;
	for (auto it : graph[node]) {
		if (it.f == pa)continue;
		findborders(it.f,node,b+borders[it.f]);
	}
	return;
}

int timer = 1;
void eulertour(int node, int pa) {
	in[node] = timer;
	++timer;
	for (auto it : graph[node]) {
		if (it.f == pa) {
			edges[it.s] = {it.f,node};
			continue;
		}
		eulertour(it.f,node);
	}
	out[node] = timer;
	return;
}

int findlca(int a, int b) {
	if (height[a] != height[b]) {
		if (height[b] < height[a]) {
			swap(a,b);
		}
		for (int dist = height[b]-height[a]; dist > 0; dist -= dist&-dist) {
			b = bl[b][(int)log2(dist&-dist)];
		}
	}
	int cap1 = floor(log2(n));
	for (;a != b;) {
		int l = -1;
		int r = cap1;
		for (;;) {
			if (l >= r)break;
			int m = (l+r+1)/2;
			if (bl[a][m] == bl[b][m]) {
				r = m-1;
			} else {
				l = m;
			}
		}
		if (l == -1) {
			l = 0;
		}
		a = bl[a][l];
		b = bl[b][l];
		cap1 = l-1;
	}
	return a;
}

pair<long long,int> path(int amt, int u, int v, int lca) {
	pair<long long,int> qu, qv, qlca;
	qu = query(perstree[amt],1,n+1,1,in[u]);
	qv = query(perstree[amt],1,n+1,1,in[v]);
	qlca = query(perstree[amt],1,n+1,1,in[lca]);
	// printf("%lld %d %lld %d %lld %d\n",qu.f,qu.s,qv.f,qv.s,qlca.f,qlca.s);
	return {qu.f+qv.f-2*qlca.f,qu.s+qv.s-2*qlca.s};
}

int tcoins(int u, int v, int lca) {
	return total[u]+total[v]-2*total[lca];
}

int main() {
	int m, q;
	scanf("%d%d%d",&n,&m,&q);
	for (int i = 1; i <= n-1; ++i) {
		int a, b;
		scanf("%d%d",&a,&b);
		graph[a].push_back({b,i});
		graph[b].push_back({a,i});
	}
	for (int i = 0; i < m; ++i) {
		int p, c;
		scanf("%d%d",&p,&c);
		vctr.push_back({c,p});
	}
	vctr.push_back({-1,-1});
	sort(vctr.begin(),vctr.end());
	findsize(1,-1,0);
	eulertour(1,-1);
	for (auto it : vctr) {
		++borders[edges[it.s].s];
		// printf("added %d\n",edges[it.s].s);
	}
	findborders(1,-1,0);
	// for (int i = 1; i <= n; ++i) {
		// printf("%d -> %d\n",in[i],out[i]);
	// }
	// for (int j = 1; j <= n; ++j) {
		// printf("%d ",total[j]);
	// }
	// printf("\n");
	for (int k = 1; k <= 19; ++k) {
		for (int i = 1; i <= n; ++i) {
			bl[i][k] = bl[bl[i][k-1]][k-1];
		}
	}
	perstree[0] = build(1,n+1);
	// for (int j = 1; j <= n; ++j) {
		// printf("[%lld] ",query(perstree[0],1,n+1,1,in[j]).f);
	// }
	// printf("\n\n");
	for (int i = 1; i <= m; ++i) {
		// printf("%d %d : %d %d\n",edges[vctr[i].s].s,in[edges[vctr[i].s].s],edges[vctr[i].s].f,out[edges[vctr[i].s].s]);
		perstree[i] = update(perstree[i-1],1,n+1,in[edges[vctr[i].s].s],vctr[i].f,1);
		perstree[i] = update(perstree[i],1,n+1,out[edges[vctr[i].s].s],-vctr[i].f,-1);
		for (int j = 1; j <= n; ++j) {
			// printf("[%lld] ",query(perstree[i],1,n+1,1,in[j]).f);
		}
		// printf("\n\n");
	}
	// for (int i = 0; i <= m; ++i) {
	// 	for (int j = 1; j <= n; ++j) {
			// printf("%lld ",query(perstree[i],1,n+1,1,in[j]).f);
	// 	}
		// printf("\n");
	// }
	for (int qi = 0; qi < q; ++qi) {
		int s, t, x;
		long long y;
		scanf("%d%d%d%lld",&s,&t,&x,&y);
		int l = 0, r = m;
		int lca = findlca(s,t);
		// printf("\n%d %d lca: %d\n",s,t,lca);
		while (true) {
			if (l >= r)break;
			int mid = (l+r+1)/2;
			long long cost = path(mid,s,t,lca).f;
			// printf("%d %lld\n",mid,cost);
			if (cost <= y) {
				l = mid;
			} else {
				r = mid-1;
			}
		}
		// printf("%d !\n\n",l);
		int coins = path(l,s,t,lca).s;
		int totalcoins = tcoins(s,t,lca);
		int pay = totalcoins-coins;
		// printf("%d %d %d\n",coins,totalcoins,pay);
		if (pay <= x) {
			printf("%d\n",x-pay);
		} else {
			printf("-1\n");
		}
	}
	return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

currencies.cpp: In function 'int main()':
currencies.cpp:168:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  168 |  scanf("%d%d%d",&n,&m,&q);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~
currencies.cpp:171:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  171 |   scanf("%d%d",&a,&b);
      |   ~~~~~^~~~~~~~~~~~~~
currencies.cpp:177:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  177 |   scanf("%d%d",&p,&c);
      |   ~~~~~^~~~~~~~~~~~~~
currencies.cpp:224:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  224 |   scanf("%d%d%d%lld",&s,&t,&x,&y);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...