Submission #122034

#TimeUsernameProblemLanguageResultExecution timeMemory
122034KLPPDesignated Cities (JOI19_designated_cities)C++14
100 / 100
1830 ms119480 KiB
#include<bits/stdc++.h>

using namespace std;
typedef long long int lld;
typedef pair<lld,lld> pii;
#define rep(i,a,b) for(int i=a;i<b;i++)
#define trav(a,v) for(auto a:v)
#define INF 1000000000000000000
vector<pii> nei[200000];
vector<pii> inv[200000];
set<int> leaves;
map<int,lld> tree[200000];
int n;
vector<int> V;
class ST{
  pii arr[1000000];
public:
  void build(int a, int b, int node){
    if(a==b){
      arr[node]=pii(0,a);
      return;
    }
    int mid=(a+b)/2;
    build(a,mid,2*node);
    build(mid+1,b,2*node+1);
    arr[node]=min(arr[2*node],arr[2*node+1]);
  }
  void update(int a, int b, int node, int pos, lld val){
    if(pos<a || b<pos)return;
    if(a==b){
      arr[node]=pii(val,pos);
      return;
    }
    int mid=(a+b)/2;
    update(a,mid,2*node,pos,val);
    update(mid+1,b,2*node+1,pos,val);
    arr[node]=min(arr[2*node],arr[2*node+1]);
  }
  int query(){
    return arr[1].second;
  }
  int query2(){
    return arr[1].first;
  }
};

ST *DEG;
ST *candidates;
void correct(){
  while(DEG->query2()==2){
    int i=DEG->query();
      //cout<<i<<endl;
      trav(x,tree[i]){
	V.push_back(x.first);
      }
      //cout<<V[0]<<" "<<V[1]<<endl;
      lld go=tree[V[0]][i]+tree[i][V[1]];
      lld come=tree[V[1]][i]+tree[i][V[0]];
      tree[V[0]].erase(tree[V[0]].find(i));
      tree[V[1]].erase(tree[V[1]].find(i));
      tree[V[0]][V[1]]=go;
      tree[V[1]][V[0]]=come;
      DEG->update(0,n-1,1,i,INF);
      
      V.clear();
      tree[i].clear();
      if(leaves.find(V[0])!=leaves.end()){
	candidates->update(0,n-1,1,V[0],go);
      }
      if(leaves.find(V[1])!=leaves.end()){
	candidates->update(0,n-1,1,V[1],come);
      }
  }
}
int view(){
  pii best=pii(1000000000000000,-1);
  trav(l,leaves){
    //cout<<l<<endl;
    pii travel=pii(-1,l);
    lld ans=0;
    while(tree[travel.second].size()==2 || travel.first==-1){
      //if(travel.first==1)cout<<travel.first<<" "<<travel.second<<" "<<tree[travel.second].size()<<endl;
      trav(u,tree[travel.second]){
	if(travel.first!=u.first){
	  travel.first=travel.second;
	  travel.second=u.first;
	  ans+=u.second;
	}
      }
    }
    best=min(best,pii(ans,l));
    //cout<<ans<<" "<<l<<endl;
  }
  return best.second;
}

bool visited[200000];
lld size[200000];
lld size2[200000];
void DFS(int node){
  visited[node]=true;
  size[node]=0;
  trav(p,nei[node]){
    if(!visited[p.first]){
      DFS(p.first);
      size[node]+=size[p.first]+p.second;
      size2[p.first]=-p.second;
    }
  }
}
 
void DFS2(int node){
  visited[node]=true;
  trav(p,inv[node]){
    if(!visited[p.first]){
      //cout<<node<<" "<<p.first<<" "<<p.second<<endl;
      size2[p.first]+=size2[node]+p.second;
      DFS2(p.first);
    }
  }
}
void print(){
  rep(i,0,n){
    trav(p,tree[i]){
      cout<<p.first<<","<<p.second<<" ";
    }
    cout<<endl;
  }
}
int main(){
  scanf("%d",&n);
  rep(i,0,n-1){
    int x,y;
    lld z,w;
    scanf("%d %d %lld %lld",&x,&y,&z,&w);
    x--;y--;
    tree[x][y]=w;
    tree[y][x]=z;
    nei[x].push_back(pii(y,z));
    nei[y].push_back(pii(x,w));
    inv[x].push_back(pii(y,w));
    inv[y].push_back(pii(x,z));
  }
  DEG=new ST();
  candidates=new ST();
  DEG->build(0,n-1,1);
  candidates->build(0,n-1,1);
  rep(i,0,n){
    if(tree[i].size()==1){
      leaves.insert(i);
      candidates->update(0,n-1,1,i,tree[i].begin()->second);
      DEG->update(0,n-1,1,i,INF);
    }else{
      candidates->update(0,n-1,1,i,INF);
      DEG->update(0,n-1,1,i,tree[i].size());
    }
  }
  lld answer[n+1];
  rep(i,leaves.size(),n){
    answer[i]=0;
  }
  
  correct();
  lld ans=0;
  while(leaves.size()>2){
    int u=candidates->query();
    pii p=*tree[u].begin();
    tree[u].clear();
    ans+=p.second;
    tree[p.first].erase(tree[p.first].find(u));
    DEG->update(0,n-1,1,p.first,tree[p.first].size());
    correct();
    //cout<<tree[0].size()<<endl;
    //print();
    leaves.erase(u);
    candidates->update(0,n-1,1,u,INF);
    answer[leaves.size()]=ans;
    //cout<<ans<<endl;
  }
  rep(i,0,n)visited[i]=false;
  DFS(0);
  size2[0]=size[0];
  rep(i,0,n)visited[i]=false;
  DFS2(0);
  answer[1]=size2[0];
  rep(i,0,n)answer[1]=min(answer[1],size2[i]);
  int q;
  scanf("%d",&q);
  while(q--){
    int x;
    scanf("%d",&x);
    printf("%lld\n",answer[x]);
  }
  
  return 0;
}

Compilation message (stderr)

designated_cities.cpp: In function 'int main()':
designated_cities.cpp:131:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d",&n);
   ~~~~~^~~~~~~~~
designated_cities.cpp:135:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d %d %lld %lld",&x,&y,&z,&w);
     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
designated_cities.cpp:188:8: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
   scanf("%d",&q);
   ~~~~~^~~~~~~~~
designated_cities.cpp:191:10: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
     scanf("%d",&x);
     ~~~~~^~~~~~~~~
#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...