제출 #1091744

#제출 시각아이디문제언어결과실행 시간메모리
1091744Zero_OPMin-max tree (BOI18_minmaxtree)C++14
0 / 100
1078 ms22856 KiB
#include<bits/stdc++.h> using namespace std; #define sz(v) (int)v.size() #define all(v) begin(v), end(v) #define compact(v) v.erase(unique(all(v)), end(v)) #define dbg(v) "[" #v " = " << (v) << "]" #define file(name) if(fopen(name".inp", "r")) {freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); } #define rep(i, l, r) for(int i = (l); i < (r); ++i) using ll = long long; using vi = vector<int>; using vl = vector<long long>; using ld = long double; template<typename T> bool minimize(T& a, const T& b){ if(a > b){ return a = b, true; } return false; } template<typename T> bool maximize(T& a, const T& b){ if(a < b){ return a = b, true; } return false; } template<int dimension, typename T> struct tensor : public vector<tensor<dimension - 1, T>> { static_assert(dimension > 0, "Dimension must be positive !\n"); template<typename... Args> tensor(int n = 0, Args... args) : vector<tensor<dimension - 1, T>> (n, tensor<dimension - 1, T>(args...)) {} }; template<typename T> struct tensor<1, T> : public vector<T> { tensor(int n = 0, T val = T()) : vector<T>(n, val) {} }; const int INF = 1e7 + 5; struct MaximumBipartiteMatching { int n; vector< vector<int> > ke; vector< bool > seen; vector< int > matchL, matchR; MaximumBipartiteMatching(int n) : n(n), ke(n), seen(n, false), matchL(n, -1), matchR(n, -1) {} void addEdge(int u, int v) { ke[u].push_back(v); } bool bpm(int u) { for(__typeof(ke[u].begin()) v = ke[u].begin(); v != ke[u].end(); ++v) { if (seen[*v]) continue; seen[*v] = true; if (matchR[*v] < 0 || bpm(matchR[*v])) { matchL[u] = *v; matchR[*v] = u; return true; } } return false; } int match() { int res = 0; for(int i = 0; i < n; ++i) { for(int i = 0; i < n; ++i) seen[i] = false; if (bpm(i)) ++res; } return res; } }; const int MAX = 7e4 + 5; const int inf = 1e9 + 7; int n, q, head[MAX], depth[MAX], sz[MAX], heavy[MAX], par[MAX], pos[MAX], timerHLD; vector<int> adj[MAX]; pair<int, int> st[2][MAX << 2]; int id[2][MAX << 2]; void combine(int type, pair<int, int>& cur, const pair<int, int>& nw){ if(type == 0) minimize(cur, nw); else maximize(cur, nw); } void init(int id, int l, int r){ if(l < r){ int mid = l + r >> 1; init(id << 1, l, mid); init(id << 1 | 1, mid + 1, r); } st[0][id] = {+inf, -1}; st[1][id] = {-inf, -1}; } void update(int type, int id, int l, int r, int u, int v, const pair<int, int>& val){ if(u <= l && r <= v){ combine(type, st[type][id], val); } else{ int mid = l + r >> 1; if(u <= mid) update(type, id << 1, l, mid, u, v, val); if(mid < v) update(type, id << 1 | 1, mid + 1, r, u, v, val); } } void solve(int id, int l, int r){ if(l == r){ // cout << l << " : " << st[0][id].second << ' ' << st[1][id].second << '\n'; ::id[0][l] = st[0][id].second; ::id[1][l] = st[1][id].second; } else{ int mid = l + r >> 1; for(int i = 0; i < 2; ++i){ combine(i, st[i][id << 1], st[i][id]); combine(i, st[i][id << 1 | 1], st[i][id]); } solve(id << 1, l, mid); solve(id << 1 | 1, mid + 1, r); } } void dfs(int u){ sz[u] = 1; for(int v : adj[u]){ adj[v].erase(find(all(adj[v]), u)); depth[v] = depth[u] + 1; par[v] = u; dfs(v); sz[u] += sz[v]; if(sz[heavy[u]] < sz[v]){ heavy[u] = v; } } } void dfsHLD(int u, int chain){ head[u] = chain; pos[u] = ++timerHLD; if(heavy[u]){ dfsHLD(heavy[u], chain); for(int v : adj[u]){ if(v != heavy[u]){ dfsHLD(v, v); } } } } int getLCA(int u, int v){ while(head[u] != head[v]){ if(depth[head[u]] < depth[head[v]]) swap(u, v); u = par[head[u]]; } return (depth[u] < depth[v] ? u : v); } int queries[MAX]; void updatePath(int type, int u, int v, pair<int, int> val){ while(head[u] != head[v]){ if(depth[head[u]] < depth[head[v]]) swap(u, v); update(type, 1, 1, n, pos[head[u]], pos[u], val); u = par[head[u]]; } if(pos[u] > pos[v]) swap(u, v); if(pos[u] < pos[v]) update(type, 1, 1, n, pos[u] + 1, pos[v], val); } void testcase(){ cin >> n; for(int i = 1; i < n; ++i){ int u, v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } dfs(1); dfsHLD(1, 1); init(1, 1, n); cin >> q; for(int i = 1; i <= q; ++i){ char op; int u, v, w; cin >> op >> u >> v >> w; int type = (op == 'm' ? 0 : 1); updatePath(type, u, v, make_pair(w, i)); queries[i] = w; } solve(1, 1, n); MaximumBipartiteMatching Match(n + q + 1); for(int i = 2; i <= n; ++i){ int minEdge = id[0][pos[i]], maxEdge = id[1][pos[i]]; // cout << i << ' ' << minEdge << '\n'; if(minEdge != -1){ Match.addEdge(i, n + minEdge); } // cout << i << ' ' << maxEdge << '\n'; if(maxEdge != -1){ Match.addEdge(i, n + maxEdge); } } int ret = Match.match(); vector<int> resEdge(n + 1); for(int i = 2; i <= n; ++i){ if(Match.matchL[i] >= 0){ resEdge[i] = queries[Match.matchL[i] - n]; } else{ resEdge[i] = inf; } } for(int i = 2; i <= n; ++i){ cout << par[i] << ' ' << i << ' ' << resEdge[i] << '\n'; } } int main(){ ios_base::sync_with_stdio(0); cin.tie(0); file("task"); int T = 1; // cin >> T; while(T--){ testcase(); } return 0; }

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

minmaxtree.cpp: In function 'void init(int, int, int)':
minmaxtree.cpp:97:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   97 |         int mid = l + r >> 1;
      |                   ~~^~~
minmaxtree.cpp: In function 'void update(int, int, int, int, int, int, const std::pair<int, int>&)':
minmaxtree.cpp:110:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  110 |         int mid = l + r >> 1;
      |                   ~~^~~
minmaxtree.cpp: In function 'void solve(int, int, int)':
minmaxtree.cpp:122:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  122 |         int mid = l + r >> 1;
      |                   ~~^~~
minmaxtree.cpp: In function 'void testcase()':
minmaxtree.cpp:222:9: warning: unused variable 'ret' [-Wunused-variable]
  222 |     int ret = Match.match();
      |         ^~~
minmaxtree.cpp: In function 'int main()':
minmaxtree.cpp:9:55: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
    9 | #define file(name) if(fopen(name".inp", "r")) {freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); }
      |                                                ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
minmaxtree.cpp:241:5: note: in expansion of macro 'file'
  241 |     file("task");
      |     ^~~~
minmaxtree.cpp:9:88: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
    9 | #define file(name) if(fopen(name".inp", "r")) {freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); }
      |                                                                                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
minmaxtree.cpp:241:5: note: in expansion of macro 'file'
  241 |     file("task");
      |     ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...