Submission #892101

#TimeUsernameProblemLanguageResultExecution timeMemory
892101CutSandstoneRailway (BOI17_railway)C++17
100 / 100
79 ms23836 KiB
#include <bits/stdc++.h> // #pragma GCC optimize("O3,unroll-loops") // #pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt,tune=native") #define vi vector<int> #define vb vector<bool> #define vl vector<long long> #define vii vector<vector<int>> #define vll vector<vector<long long>> #define pi pair<int, int> #define pl pair<ll, ll> #define vpi vector<pair<int, int>> #define vpl vector<pair<ll, ll>> #define a first #define b second #define str string #define pb push_back #define hset unordered_set #define hmap unordered_map const int mod = 1e9+7; const int m = 998244353; //16094558932 using namespace std; using ll = long long; using ull = unsigned ll; template<size_t SZ> struct RMQ { static constexpr int level(int x) { return 31-__builtin_clz(x); } array<array<int,SZ>, level(SZ)+1> jmp; vi v; void init(const vi& depth, const vi& ind){ v = depth; assert(ind.size() <= SZ); copy(begin(ind), end(ind), begin(jmp[0])); for (int j = 1; 1<<j <= ind.size(); ++j) for(int i = 0; i<ind.size()-(1<<j)+1; i++){ int a = jmp[j-1][i], b = jmp[j-1][i+(1<<(j-1))]; jmp[j][i] = depth[a] < depth[b] ? a:b; } } int query(int l, int r) { if(l > r) swap(l, r); int d = level(r-l+1); int a = jmp[d][l], b = jmp[d][r-(1<<d)+1]; return v[a] < v[b] ? a:b; } }; struct BIT { int N; vl data; void init(int sz){N = sz+1; data.resize(sz+1, 0); } void add(int p, ll x) { for (p++;p<=N;p+=p&-p) data[p-1] = (data[p-1]+x)%m; } ll sum(int l, int r) { return (sum(r)-(l==0?0:sum(l-1))+m)%m; } ll sum(int r) { ll s = 0; r++; for(;r;r-=r&-r)s = (s+data[r-1])%m; return s; } int lower_bound(ll sum) { if (sum <= 0) return -1; int pos = 0; for (int pw = 1<<25; pw; pw >>= 1) { int npos = pos+pw; if (npos <= N && data[npos-1] < sum) pos = npos, sum -= data[pos-1]; } return pos; } }; struct DSU { vector<int> e; DSU(int N) { e = vector<int>(N, -1); } // get representive component (uses path compression) int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); } bool same_set(int a, int b) { return get(a) == get(b); } int size(int x) { return -e[get(x)]; } bool unite(int x, int y) { // union by size x = get(x), y = get(y); if (x == y) return false; if (e[x] > e[y]) swap(x, y); e[x] += e[y]; e[y] = x; return true; } }; struct Hasher { vl h1, h2, p1, p2, v1, v2; const ll m1 = 1283, m2 = 2793; const ll i1 = 439594703, i2 = 7876835; Hasher(string s){ int n = s.size(); h1.resize(n); h2.resize(n); p1.resize(n); p2.resize(n); v1.resize(n); v2.resize(n); for(int i = 0; i<n; i++){ p1[i] = (i?p1[i-1]:i1)*m1%mod; p2[i] = (i?p2[i-1]:i2)*m2%mod; v1[i] = (i?v1[i-1]:m1)*i1%mod; v2[i] = (i?v2[i-1]:m2)*i2%mod; h1[i] = ((i?h1[i-1]:0)+p1[i]*(s[i]-'a'+1)%mod)%mod; h2[i] = ((i?h2[i-1]:0)+p2[i]*(s[i]-'a'+1)%mod)%mod; } } pi get(int l, int r){ ll a = (h1[r]-(l?h1[l-1]:0)+mod)%mod; ll b = (h2[r]-(l?h2[l-1]:0)+mod)%mod; return {(int)(a*v1[l]%mod), (int)(b*v2[l]%mod)}; } }; struct SegTree { vll mem; int n; public: SegTree(int N){ n = N; mem.resize(n<<1, vl(4)); } void set(int ind, ll val){ for(mem[ind+=n] = {val,val,val,val}; ind>>=1;) mem[ind] = comb(mem[ind<<1], mem[ind<<1|1]); } ll get(int l, int r){ vl L = {}, R = {}; for(l+=n,r+=n+1;l<r;l>>=1,r>>=1){ if(l&1) L = comb(L, mem[l++]); if(r&1) R = comb(mem[--r], R); } return comb(L, R)[0]; } private: vl comb(vl& l, vl& r){ if(l.size() == 0) return r; if(r.size() == 0) return l; return {max({l[0], r[0], l[2]+r[1]}), max({l[3]+r[1], l[1]}), max({r[3]+l[2], r[2]}), l[3]+r[3] }; } }; class LZST { private: class Node { public: ll l, r; Node *left, *right; ll val = 0, max = 0, min = 0, add = 0; bool isSet = false; Node(ll a, ll b) : l(a), r(b), left(nullptr), right(nullptr) {} void set(ll num) { isSet = true; add = max = min = num; val = num * (r - l + 1); } void addF(ll num) { add += num; val += num * (r - l + 1); max += num; min += num; } void prop() { ll mid = (l + r) >> 1; if (left == nullptr) left = new Node(l, mid); if (right == nullptr) right = new Node(mid + 1, r); if (isSet) { isSet = false; if (l != r) { left->set(add); right->set(add); } } else if (add != 0) { if (l != r) { left->addF(add); right->addF(add); } } add = 0; } void upd() { val = left->val + right->val; min = std::min(left->min, right->min); max = std::max(left->max, right->max); } }; Node* top; void set(ll s, ll e, ll num, Node* curr) { if (curr->l == s && curr->r == e) { curr->set(num); return; } curr->prop(); if (e <= curr->left->r) set(s, e, num, curr->left); else if (s >= curr->right->l) set(s, e, num, curr->right); else { set(s, curr->left->r, num, curr->left); set(curr->right->l, e, num, curr->right); } curr->upd(); } void add(ll s, ll e, ll num, Node* curr) { if (curr->l == s && curr->r == e) { curr->addF(num); return; } curr->prop(); if (e <= curr->left->r) add(s, e, num, curr->left); else if (s >= curr->right->l) add(s, e, num, curr->right); else { add(s, curr->left->r, num, curr->left); add(curr->right->l, e, num, curr->right); } curr->upd(); } ll sum(ll s, ll e, Node* curr) { if (curr->l == s && curr->r == e) return curr->val; curr->prop(); if (e <= curr->left->r) return sum(s, e, curr->left); if (s >= curr->right->l) return sum(s, e, curr->right); return sum(s, curr->left->r, curr->left) + sum(curr->right->l, e, curr->right); } ll max(ll s, ll e, Node* curr) { if (curr->l == s && curr->r == e) return curr->max; curr->prop(); if (e <= curr->left->r) return max(s, e, curr->left); if (s >= curr->right->l) return max(s, e, curr->right); return std::max(max(s, curr->left->r, curr->left), max(curr->right->l, e, curr->right)); } ll min(ll s, ll e, Node* curr) { if (curr->l == s && curr->r == e) return curr->min; curr->prop(); if (e <= curr->left->r) return min(s, e, curr->left); if (s >= curr->right->l) return min(s, e, curr->right); return std::min(min(s, curr->left->r, curr->left), min(curr->right->l, e, curr->right)); } public: LZST(ll N) { assert(N > 0); top = new Node(0, N - 1); } ll get(ll s) { assert(s >= top->l && s <= top->r); Node* curr = top; stack<Node*> stk; while (curr->l != curr->r) { stk.push(curr); curr->prop(); if (s <= curr->left->r) curr = curr->left; else curr = curr->right; } while (!stk.empty()) stk.top()->upd(), stk.pop(); return curr->val; } ll sum(ll s, ll e) { assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e); return sum(s, e, top); } ll max(ll s, ll e) { assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e); return max(s, e, top); } ll min(ll s, ll e) { assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e); return min(s, e, top); } void add(ll s, ll e, ll num) { assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e); add(s, e, num, top); } void add(ll s, ll num) { assert(s >= top->l && s <= top->r); add(s, s, num, top); } void set(ll s, ll e, ll num) { assert(s >= top->l && s <= top->r && e >= top->l && e <= top->r && s <= e); set(s, e, num, top); } void set(ll s, ll num) { assert(s >= top->l && s <= top->r); set(s, s, num, top); } }; const string name = ""; const int MAXN = 1e5, LOGN = 18; vi g[MAXN]; int jp[MAXN][LOGN], timer = 0, tour[MAXN]; int depth[MAXN], st[MAXN], en[MAXN], cnt[MAXN]; int jump(int a, int k){ for(int i = 0; i<LOGN; i++) if((k>>i)&1) a = jp[a][i]; return a; } int lca(int a, int b){ if(depth[a] > depth[b]) swap(a, b); b = jump(b, depth[b]-depth[a]); if(a == b) return a; for(int i = LOGN-1; i>=0; i--) if(jp[a][i] != jp[b][i]){ a = jp[a][i]; b = jp[b][i]; } return jp[a][0]; } void dfs1(int s, int p){ if(p+1) depth[s] = depth[p]+1; jp[s][0] = p; tour[st[s] = timer++] = s; for(int i: g[s]) if(i != p) dfs1(i, s); en[s] = timer-1; } void dfs2(int s, int p){ for(int i: g[s]) if(i != p) dfs2(i, s); if(p != -1) cnt[p]+=cnt[s]; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); if(filesystem::exists("input.in")) freopen("input.in", "r", stdin); else if(name.size() && filesystem::exists(name+".in")){ freopen((name+".in").c_str(), "r", stdin); freopen((name+".out").c_str(), "w", stdout); } int n, m, k; cin >> n >> m >> k; vpi eg(n-1); for(int i = 0; i<n-1; i++){ int a, b; cin >> a >> b; g[--a].pb(--b); g[b].pb(a); eg[i] = {a, b}; } for(int i = 0; i<n; i++) for(int j = 0; j<LOGN; j++) jp[i][j] = -1; dfs1(0, -1); for(int i = 1; i<LOGN; i++) for(int j = 0; j<n; j++) if(jp[j][i-1] != -1) jp[j][i] = jp[jp[j][i-1]][i-1]; while(m--){ int total, top; cin >> total >> top; set<int> in; in.insert(st[--top]); while(--total){ int s; cin >> s; int g = lca(--s, top); if(g == top){ auto low = in.lower_bound(st[s]); auto high = low--; int end = -1; if(high != in.begin()) end = lca(s, tour[*low]); if(high != in.end()){ int t = lca(s, tour[*high]); if(end == -1 || depth[t] > depth[end]) end = t; } cnt[s]++; cnt[end]--; }else{ cnt[top]++; cnt[s]++; cnt[top = g]-=2; } in.insert(st[s]); } } dfs2(0, -1); vi edge(n); for(int i = 0; i<n-1; i++) if(depth[eg[i].a] > depth[eg[i].b]) edge[eg[i].a] = i+1; else edge[eg[i].b] = i+1; vi ans; for(int i = 0; i<n; i++) if(cnt[i] >= k) ans.pb(edge[i]); sort(ans.begin(), ans.end()); cout << ans.size() << "\n"; for(int i: ans) cout << i << " "; cout << "\n"; }

Compilation message (stderr)

railway.cpp: In function 'int main()':
railway.cpp:317:44: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  317 |  if(filesystem::exists("input.in")) freopen("input.in", "r", stdin);
      |                                     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
railway.cpp:319:10: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  319 |   freopen((name+".in").c_str(), "r", stdin);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
railway.cpp:320:10: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  320 |   freopen((name+".out").c_str(), "w", stdout);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...