This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
const int NMAX = 1e5;
struct data_t{
int tree_id;
int st;
int dr;
int father;
data_t(){
tree_id = st = dr = father = 0;
}
data_t(int tree_id,int st,int dr,int father){
this->tree_id = tree_id;
this->st = st;
this->dr = dr;
this->father = father;
}
bool operator < (const data_t &other)const{
if(tree_id != other.tree_id){
return tree_id < other.tree_id;
}
if(st != other.st){
return st < other.st;
}
if(dr != other.dr){
return dr < other.dr;
}
return father < other.father;
}
};
struct my_map{
vector<pair<int,data_t> > v;
my_map(){
v.clear();
}
void add(int key,data_t data){
v.push_back({key,data});
}
void build(){
sort(v.begin(),v.end());
}
data_t get(int id){
return lower_bound(v.begin(),v.end(),make_pair(id,data_t()))->second;
}
};
class SegTree{
int n;
vector <long long> aint;
vector <long long> lazy;
void propag(int nod,int st,int dr){
if(lazy[nod] == 0 || st == dr){
return ;
}
aint[nod * 2] += lazy[nod];
lazy[nod * 2] += lazy[nod];
aint[nod * 2 + 1] += lazy[nod];
lazy[nod * 2 + 1] += lazy[nod];
lazy[nod] = 0;
}
void update(int nod,int st,int dr,int l,int r,long long delta){
propag(nod,st,dr);
if(dr < l || st > r){
return ;
}
if(l <= st && dr <= r){
aint[nod] += delta;
lazy[nod] += delta;
return ;
}
int mid = (st + dr) / 2;
update(nod * 2,st,mid,l,r,delta);
update(nod * 2 + 1,mid + 1,dr,l,r,delta);
aint[nod] = max(aint[nod * 2],aint[nod * 2 + 1]);
}
public:
SegTree(int n){
this->n = n;
aint = vector<long long>(4 * n + 1,0);
lazy = vector<long long>(4 * n + 1,0);
}
void update(int l,int r,long long val){
update(1,1,n,l,r,val);
}
long long query(){
return aint[1];
}
};
int n,q;
long long w;
bool viz[NMAX + 5];
int weight[NMAX + 5];
vector<int> graph[NMAX + 5];
pair<int,int> edge[NMAX + 5];
long long cost[NMAX + 5];
int cen_father[NMAX + 5];
int cen_lvl[NMAX + 5];
class RootPathSolver{
int lst;
int root;
vector< SegTree > trees;
my_map stuff;
set<pair<long long,int> > answers;//(best path,tree id)
void dfs(int nod,int tata,int id){
data_t tmp(id,++lst,-1,tata);
weight[nod] = 1;
for(auto it:graph[nod]){
if(it == tata || viz[it] == true){
continue;
}
dfs(it,nod,id);
weight[nod] += weight[it];
}
tmp.dr = lst;
stuff.add(nod,tmp);
}
public:
RootPathSolver(){
}
RootPathSolver(int root){
this->root = root;
this->stuff = my_map();
int lst_id = -1;
for(auto it:graph[root]){
if(viz[it] == false){
lst = 0;
dfs(it,root,++lst_id);
trees.push_back(SegTree(weight[it]));
answers.insert({0,it});
}
}
this->stuff.build();
}
void update(pair<int,int> edge,long long delta){
data_t tmp = stuff.get(edge.second);
if(edge.second == root || tmp.father != edge.first){
swap(edge.second,edge.first);
tmp = stuff.get(edge.second);
}
answers.erase({trees[tmp.tree_id].query(),tmp.tree_id});
trees[tmp.tree_id].update(tmp.st,tmp.dr,delta);
answers.insert({trees[tmp.tree_id].query(),tmp.tree_id});
}
long long query(){
if(answers.empty()){
return 0;
}
else if(answers.size() == 1){
return answers.rbegin()->first;
}
else{
return (answers.rbegin())->first + (next(answers.rbegin()))->first;
}
}
};
class Centroid{
int root;
vector<RootPathSolver> chestie;
set<pair<long long,int> > answers;
void dfs(int nod,int tata){
weight[nod] = 1;
for(auto it:graph[nod]){
if(it == tata || viz[it] == true){
continue;
}
dfs(it,nod);
weight[nod] += weight[it];
}
}
int centroid(int nod,int lvl = 1){
dfs(nod,0);
int total_weight = weight[nod];
int root = nod;
while(true){
int bst = -1;
for(auto it:graph[root]){
if(viz[it] == true || it == nod){
continue;
}
if(bst == -1 || weight[it] > weight[bst]){
bst = it;
}
}
if(bst != -1 && weight[bst] * 2 > total_weight){
nod = root;
root = bst;
}
else{
break;
}
}
viz[root] = true;
chestie[root] = RootPathSolver(root);
cen_lvl[root] = lvl;
answers.insert({0,root});
for(auto it:graph[root]){
if(viz[it] == false){
int tmp = centroid(it,cen_lvl[root] + 1);
cen_father[tmp] = root;
}
}
return root;
}
public:
Centroid(int n){
this->chestie = vector<RootPathSolver>(n + 1,RootPathSolver());
this->root = centroid(1);
}
void update(pair<int,int> edge,long long delta){
if(cen_lvl[edge.first] > cen_lvl[edge.second]){
swap(edge.first,edge.second);
}
int nod = edge.first;
while(nod){
answers.erase({chestie[nod].query(),nod});
chestie[nod].update(edge,delta);
answers.insert({chestie[nod].query(),nod});
nod = cen_father[nod];
}
}
long long query(){
return answers.rbegin()->first;
}
};
const int LEN = 1 << 12;
char buff[LEN];
int ind = LEN - 1;
int i32(){
int ans = 0;
while(buff[ind] < '0' || buff[ind] > '9'){
if(++ind >= LEN){
ind = 0;
fread(buff,1,LEN,stdin);
}
}
while(!(buff[ind] < '0' || buff[ind] > '9')){
ans = ans * 10 + buff[ind] - '0';
if(++ind >= LEN){
ind = 0;
fread(buff,1,LEN,stdin);
}
}
return ans;
}
long long i64(){
long long ans = 0;
while(buff[ind] < '0' || buff[ind] > '9'){
if(++ind >= LEN){
ind = 0;
fread(buff,1,LEN,stdin);
}
}
while(!(buff[ind] < '0' || buff[ind] > '9')){
ans = ans * 10 + buff[ind] - '0';
if(++ind >= LEN){
ind = 0;
fread(buff,1,LEN,stdin);
}
}
return ans;
}
int main(){
n = i32();
q = i32();
w = i64();
for(int i = 1;i < n;i++){
edge[i].first = i32();
edge[i].second = i32();
cost[i] = i64();
graph[edge[i].first].push_back(edge[i].second);
graph[edge[i].second].push_back(edge[i].first);
}
Centroid a(n);
for(int i = 1;i < n;i++){
a.update(edge[i],cost[i]);
}
long long last = 0;
while(q--){
int d;
long long e;
d = i32();
e = i64();
d = (d + last) % (n - 1) + 1;
e = (e + last) % w;
a.update(edge[d],e - cost[d]);
cost[d] = e;
last = a.query();
printf("%lld\n",last);
}
return 0;
}
Compilation message (stderr)
diameter.cpp: In function 'int i32()':
diameter.cpp:291:18: warning: ignoring return value of 'size_t fread(void*, size_t, size_t, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
fread(buff,1,LEN,stdin);
~~~~~^~~~~~~~~~~~~~~~~~
diameter.cpp:299:18: warning: ignoring return value of 'size_t fread(void*, size_t, size_t, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
fread(buff,1,LEN,stdin);
~~~~~^~~~~~~~~~~~~~~~~~
diameter.cpp: In function 'long long int i64()':
diameter.cpp:311:18: warning: ignoring return value of 'size_t fread(void*, size_t, size_t, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
fread(buff,1,LEN,stdin);
~~~~~^~~~~~~~~~~~~~~~~~
diameter.cpp:319:18: warning: ignoring return value of 'size_t fread(void*, size_t, size_t, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
fread(buff,1,LEN,stdin);
~~~~~^~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |