Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*input
- */
- #include<bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- using namespace std;
- using namespace __gnu_pbds;
- #define int long long
- #define double long double
- #define f first
- #define s second
- #define mp make_pair
- #define pb push_back
- #define RE(i,n) for (int i = 1; i <= n; i++)
- #define RED(i,n) for (int i = n; i > 0; i--)
- #define REPS(i,n) for(int i = 1; (i*i) <= n; i++)
- #define REP(i,n) for (int i = 0; i < (int)n; i++)
- #define FOR(i,a,b) for (int i = a; i < b; i++)
- #define REPD(i,n) for (int i = n-1; i >= 0; i--)
- #define FORD(i,a,b) for (int i = a; i >= b; i--)
- #define all(v) v.begin(),v.end()
- #define pii pair<int,int>
- #define vi vector<int>
- #define vvi vector<vi>
- #define print(arr) for (auto it = arr.begin(); it != arr.end(); ++it) cout << *it << " "; cout << endl;
- #define debug(x) cout << x << endl;
- #define debug2(x,y) cout << x << " " << y << endl;
- #define debug3(x,y,z) cout << x << " " << y << " " << z << endl;
- typedef tree<
- int,
- null_type,
- less<int>,
- rb_tree_tag,
- tree_order_statistics_node_update>
- ordered_set;
- const int INF = 1e18+1;
- const int MOD = 1e9+7;
- const double PI = 3.14159265358979323846264338;
- int raise(int a,int n,int m = MOD){
- if(n == 0)return 1;
- if(n == 1)return a;
- int x = 1;
- x *= raise(a,n/2,m);
- x %= m;
- x *= x;
- x %= m;
- if(n%2)x*= a;
- x %= m;
- return x;
- }
- int floor1(int n,int k){
- if(n%k == 0 || n >= 0)return n/k;
- return (n/k)-1;
- }
- int ceil1(int n,int k){
- return floor1(n+k-1,k);
- }
- // first to dfs to calculate numbers and
- // need persistent segtree on dfs numbers
- // need to write binary search
- const int N = 2e5+1;
- int n,e;
- vector<int> adj[N];
- int sub[N];
- int en[N];
- int dist[N];
- int inv[N];
- int ans[N];
- int x[N];
- int y[N];
- int z[N];
- int cur = 0;
- void ini(){
- cur = 0;
- dist[1] = 0;
- RE(i,n){
- adj[i].clear();
- }
- }
- struct node{
- int cnt,sum;
- node *l,*r;
- node(){
- cnt = 0;
- sum = 0;
- l = NULL;
- r = NULL;
- }
- node(int a,int b,node* l1,node* r1){
- cnt = a;
- sum = b;
- l = l1;
- r = r1;
- }
- };
- node *roots[N];
- void dfs(int u,int p){
- cur++;
- inv[cur] = u;
- en[u] = cur;
- sub[u] = 1;
- for(int v:adj[u]){
- if(v == p)continue;
- dist[v] = dist[u]+1;
- dfs(v,u);
- sub[u] += sub[v];
- }
- }
- #define mid (le+re)/2
- #define child 2*node
- // remember to undef this XD
- void build(node* cur,int le,int re){
- if(le == re)return;
- cur->l = new node();
- cur->r = new node();
- build(cur->l,le,mid);
- build(cur->r,mid+1,re);
- }
- node* inse(node* cur,int le,int re,int ind){
- if(ind > re or ind < le)return cur;
- if(le == re){
- return new node(cur->cnt+1,cur->sum+ind,NULL,NULL);
- }
- node* res = new node(cur->cnt+1,cur->sum+ind,inse(cur->l,le,mid,ind),inse(cur->r,mid+1,re,ind));
- return res;
- }
- int query(node* st,node* ent,int le,int re,int left,int cursum){
- if(le == re){
- return cursum+left*le;
- }
- if(ent->r->cnt-st->r->cnt >= left)return query(st->r,ent->r,mid+1,re,left,cursum);
- int addsum = ent->r->sum-st->r->sum;
- int lesscnt = ent->r->cnt-st->r->cnt;
- return query(st->l,ent->l,le,mid,left-lesscnt,cursum+addsum);
- }
- int querys(node* st,node* ent,int le,int re,int left,int cursum){
- if(le == re){
- return cursum+left*le;
- }
- if(ent->l->cnt-st->l->cnt >= left)return querys(st->l,ent->l,le,mid,left,cursum);
- int addsum = ent->l->sum-st->l->sum;
- int lesscnt = ent->l->cnt-st->l->cnt;
- return querys(st->r,ent->r,mid+1,re,left-lesscnt,cursum+addsum);
- }
- #undef mid
- //haha done nice nice
- int resL1(int node,int place){
- int res = place*(place+1);
- return res/2;
- }
- int resR1(int node,int place){
- int tot = dist[node]*(dist[node]-1);
- int place1 = dist[node]-1-place;
- int minus = place1*(place1+1);
- return (tot-minus)/2;
- }
- int resL2(int node,int place){
- return querys(roots[en[node]],roots[en[node]+sub[node]-1],1,n,place,0);
- }
- int resR2(int node,int place){
- return query(roots[en[node]],roots[en[node]+sub[node]-1],1,n,place,0);
- }
- int val = 0;
- int LRE(int node,int above){
- assert(above >= x[node]);
- assert(e-above >= y[node]);
- assert(above <= dist[node]-1);
- assert(e-above <= sub[node]-1);
- int l1 = resL1(node,above);
- int r1 = resR1(node,above);
- int l2 = resL2(node,e-above);
- int r2 = resR2(node,e-above);
- l2 -= (e-above)*dist[node];
- r2 -= (e-above)*dist[node];
- l1 += z[node];
- r1 += z[node];
- if(r1 < l2){
- val = l2-r1;
- return 1;
- }
- else if(r2 < l1){
- val = l1-r2;
- return 2;
- }
- val = 0;
- return 0;
- }
- void solve(){
- cin >> n >> e;
- ini();
- RE(i,n-1){
- int a,b;cin >>a >> b;
- adj[a].pb(b);
- adj[b].pb(a);
- }
- RE(i,n){
- cin >> x[i] >> y[i] >> z[i];
- }
- dist[1] = 1;
- dfs(1,0);
- roots[0] = new node();
- build(roots[0],1,n);
- RE(i,n){
- roots[i] = inse(roots[i-1],1,n,dist[inv[i]]);
- }
- RE(i,n){
- int lo = x[i];
- int hi = e-y[i];
- hi = min(hi,dist[i]-1);
- if(sub[i]-1+dist[i]-1 < e or lo > hi or lo > dist[i]-1){
- ans[i] = -1;
- continue;
- }
- lo = max(lo,e-sub[i]+1);
- int intial = LRE(i,lo);
- int final = LRE(i,hi);
- if(intial == final){
- LRE(i,lo);
- ans[i] = val;
- LRE(i,hi);
- ans[i] = min(ans[i],val);
- continue;
- }
- while(lo < hi){
- int mid = (lo+hi)/2;
- int whatcase = LRE(i,mid);
- if(whatcase == intial)lo = mid+1;
- else{
- hi = mid;
- }
- }
- LRE(i,lo-1);
- ans[i] = val;
- LRE(i,lo);
- ans[i] = min(ans[i],val);
- }
- RE(i,n){
- cout << ans[i] << " ";
- }
- cout << endl;
- }
- signed main(){
- ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
- int t = 1;
- cin >> t;
- while(t--){
- solve();
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment