제출 #201169

#제출 시각아이디문제언어결과실행 시간메모리
201169georgerapeanuDynamic Diameter (CEOI19_diameter)C++11
7 / 100
5093 ms335088 KiB
#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

const int NMAX = 1e5;

struct node_t{
    vector<pair<long long,int> > bst_nodes;
    long long lazy;
    long long bst;
    long long bst2;

    node_t(){
        bst_nodes = vector<pair<long long,int>>();
        lazy = 0;
        bst = 0;
        bst2 = -1e18;
    }

    node_t(long long val,int tag){
        bst_nodes = vector<pair<long long,int>>(1,{val,tag});
        lazy = 0;
        bst = val;
        bst2 = -1e18;
    }

    node_t operator + (const node_t &other){
        node_t ans;
        ans.lazy = 0;
        ans.bst = max(this->bst,other.bst);
        ans.bst2 = max(this->bst2,other.bst2);

        for(auto it:bst_nodes){
            ans.bst_nodes.push_back(it);
        }
        for(auto it:other.bst_nodes){
            ans.bst_nodes.push_back(it);
        }

        sort(ans.bst_nodes.begin(),ans.bst_nodes.end());
        reverse(ans.bst_nodes.begin(),ans.bst_nodes.end());

        int id = 1;

        while(id < (int)ans.bst_nodes.size() && ans.bst_nodes[id].second == ans.bst_nodes[0].second){
            id++;
        }

        if(id < (int)ans.bst_nodes.size()){
            ans.bst_nodes[1] = ans.bst_nodes[id];
            ans.bst_nodes.resize(2);
            ans.bst2 = max(ans.bst2,ans.bst_nodes[0].first + ans.bst_nodes[1].first);
        }
        else{
            ans.bst_nodes.resize(1);
        }

        for(auto it:ans.bst_nodes){
            ans.bst = max(ans.bst,it.first);
        }

        return ans;
    }

    void propag(long long val){
        lazy += val;
        for(auto &it:bst_nodes){
            it.first += val;
        }
        bst += val;
        bst2 += 2 * val;
    }
};

int tmp_tag[NMAX + 5];

class SegTree{
    int n;
    vector<node_t> aint;

    void build(int nod,int st,int dr){
        if(st == dr){
            aint[nod] = {node_t(0,tmp_tag[st])};
            return ;
        }
        int mid = (st + dr) / 2;
        build(nod * 2,st,mid);
        build(nod * 2 + 1,mid + 1,dr);
        aint[nod] = aint[nod * 2] + aint[nod * 2 + 1];
    }

    void update(int nod,int st,int dr,int l,int r,long long delta){
        if(st != dr && aint[nod].lazy != 0){
            aint[nod * 2].propag(aint[nod].lazy);
            aint[nod * 2 + 1].propag(aint[nod].lazy);
            aint[nod].lazy = 0;
        }
        if(r < st || l > dr){
            return ;
        }
        if(l <= st && dr <= r){
            aint[nod].propag(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] = aint[nod * 2] + aint[nod * 2 + 1];
    }

public:

    SegTree(){
        n = 0;
        aint = vector<node_t> (vector<node_t> ());
    }

    SegTree(int n){
        this->n = n;
        this->aint = vector<node_t> (4 * n + 1,node_t());
        build(1,1,n);
    }

    void update(const pair<int,int> &segm,long long delta){
        update(1,1,n,segm.first,segm.second,delta);
    }

    long long query(){
        return max(aint[1].bst,aint[1].bst2);
    }
};

int n,q;
long long w;

pair<int,int> edge[NMAX + 5];
long long cost[NMAX + 5];

vector<int> graph[NMAX + 5];

int viz[NMAX + 5];
int weight[NMAX + 5];

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];
    }
}

vector<pair<int,pair<int,int>> > stuff[NMAX + 5];//(centroid,pos in lin of centroid)
SegTree trees[NMAX + 5];

set<pair<long long,int>> s;

void dfs2(int nod,int tata,const int &root,int &lst,int tag){
    if(nod != root){
        lst++;
        stuff[nod].push_back({root,{lst,0}});
        if(tag == root){
            tag = nod;    
        }
        tmp_tag[lst] = tag;
    }
    for(auto it:graph[nod]){
        if(it == tata || viz[it] == true){
            continue;
        }
        dfs2(it,nod,root,lst,tag);
    }
    if(nod != root){
        stuff[nod].back().second.second = lst;
    }
}

int centroid(int nod){
    dfs(nod,0);
    int root = nod;
    int total_weight = weight[nod];

    while(true){
        int bst = -1;
        for(auto it:graph[root]){
            if(nod != it && viz[it] == false && (bst == -1 || weight[bst] < weight[it])){
                bst = it;
            }
        }
        if(bst == -1 || weight[bst] * 2 <= total_weight){
            break;
        }
        nod = root;
        root = bst;
    }

    viz[root] = true;
    int a = 0;
    dfs2(root,0,root,a,root);
    trees[root] = SegTree(total_weight);
    s.insert({0,root});    

    for(auto it:graph[root]){
        if(viz[it] == false){
            centroid(it);
        }
    }

    return root;
}

int answer[NMAX + 5];

void update(pair<int,int> edge,long long c){
    if(stuff[edge.first].empty() == false && stuff[edge.first].back().first == edge.second){
        swap(edge.first,edge.second);
    }
    for(auto it:stuff[edge.second]){
        s.erase({answer[it.first],it.first});
        trees[it.first].update(it.second,c);
        answer[it.first] = trees[it.first].query();
        s.insert({answer[it.first],it.first});
    }
}

long long query(){
    return s.rbegin()->first;
}

int main(){

    scanf("%d %d %lld",&n,&q,&w);

    for(int i = 1;i < n;i++){
        scanf("%d %d %lld",&edge[i].first,&edge[i].second,&cost[i]);
        graph[edge[i].first].push_back(edge[i].second);
        graph[edge[i].second].push_back(edge[i].first);
    }

    int root = centroid(1);

    for(int i = 1;i < n;i++){
        update(edge[i],cost[i]);
    }

    long long last = 0;

    //for(int i = 1;i <= n;i++){printf("node %d\n",i);for(auto it:stuff[i])printf("deb %d %d %d\n",it.first,it.second.first,it.second.second);printf("\n");}

    while(q--){
        int d;
        long long e;
        scanf("%d %lld",&d,&e);
        d = (d + last) % (n - 1);d++;
        e = (e + last) % w;
        update(edge[d],e - cost[d]);
        cost[d] = e;
        last = query();
        printf("%lld\n",last);
    }

    return 0;
}

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

diameter.cpp: In function 'int main()':
diameter.cpp:248:9: warning: unused variable 'root' [-Wunused-variable]
     int root = centroid(1);
         ^~~~
diameter.cpp:240:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d %d %lld",&n,&q,&w);
     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:243:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d %d %lld",&edge[i].first,&edge[i].second,&cost[i]);
         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:261:14: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
         scanf("%d %lld",&d,&e);
         ~~~~~^~~~~~~~~~~~~~~~~
#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...