Submission #201502

#TimeUsernameProblemLanguageResultExecution timeMemory
201502georgerapeanuDynamic Diameter (CEOI19_diameter)C++11
49 / 100
5078 ms162876 KiB
#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 timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...