Submission #1150649

#TimeUsernameProblemLanguageResultExecution timeMemory
1150649sofiefuInside information (BOI21_servers)C++20
2 / 100
179 ms153964 KiB
#include <bits/stdc++.h> using namespace std; #define int long long #define vo vector #define pb push_back #define se second #define fi first #define all(v) v.begin(), v.end() typedef vector<int> vi; typedef pair<int, int> pii; #define rep(i, a, b) for(int i=(a); i<b; i++) #define pr1(x) cerr << #x << '=' << x << ' '; //for google contests #define umap unordered_map #define uset unordered_set #define repd(i, a, b) for(int i=(b-1); i >= a; i--) void _pr(signed x) {cerr << x;} void _pr(long long x) {cerr << x;} void _pr(size_t x) {cerr << x;} void _pr(string &x) {cerr << x;} void _pr(double x) {cerr << x;} void _pr(char x) {cerr << '\'' << x << '\'';} void _pr(const char* x) {cerr << x;} void _pr(bool x) {cerr << (x ? "true" : "false");} template<typename T, typename V> void _pr(const pair<T, V> &x); template<typename T, typename V> void _pr(const pair<T, V> &x) {cerr << "\e[95m" << "[ "; _pr(x.first); cerr << ", "; _pr(x.second); cerr << "\e[95m" << ']';} template<typename T> void _pr(const T &x) {int F=0; cerr << '{'; for(auto &i: x) cerr << (F++ ? ", " : ""), _pr(i); cerr << "\e[91m" << '}';} template <typename T, typename... V> void _pr(T t, V... v) {_pr(t); if(sizeof...(v)) cerr << ", "; _pr(v...);} #define pr(x...) cerr << "\e[91m" << __func__ << ':' << __LINE__ << " [" << #x << "] = ["; _pr(x); cerr << "\e[91m" << ']' << "\033[0m" << endl; mt19937 mt_rng(chrono::steady_clock::now().time_since_epoch().count()); int rand(int l, int r){return uniform_int_distribution<int>(l, r)(mt_rng);} //go for outline with ;, then details int const inf = 1e18, mxn = 1e5+2e4+5; int const mxlog = 25; int n, q, parEdge[mxn]; vo<vo<pii>> adj(mxn); int bl[mxn][mxlog], dep[mxn]; struct T{ int firstval, lastval, incr, decr, maxedge; }; T dp[mxn][mxlog]; void dfs(int at, int p, int depth, int prevind){ dep[at] = depth; bl[at][0] = p; dp[at][0] = {prevind, prevind, 1, 1, prevind}; rep(i, 1, mxlog){ int anc = bl[at][i-1]; bl[at][i] = bl[anc][i-1]; dp[at][i].incr = dp[at][i-1].incr & dp[anc][i-1].incr & (dp[at][i-1].lastval < dp[anc][i-1].firstval); dp[at][i].decr = dp[at][i-1].decr & dp[anc][i-1].decr & (dp[at][i-1].lastval > dp[anc][i-1].firstval); dp[at][i].maxedge = max(dp[at][i-1].maxedge, dp[bl[at][i-1]][i-1].maxedge); dp[at][i].firstval = dp[at][i-1].firstval; dp[at][i].lastval = dp[anc][i-1].lastval; } for(auto [x, ind]: adj[at]){ if(x==p) continue; dfs(x, at, depth+1, ind); } } int jmp(int v, int d){ rep(i, 0, mxlog){ if((d>>i) & 1) v = bl[v][i]; } return v; } int LCA(int a, int b){ if(dep[a] < dep[b]) swap(a, b); int d = dep[a]-dep[b]; a = jmp(a, d); if(a==b) return a; repd(i, 0, mxlog){ if(bl[a][i] != bl[b][i]){ a = bl[a][i], b = bl[b][i]; } } return bl[a][0]; } void combine(int &a, int &b){ a &= b; } array<int, 4> lift(int v, int d){ // return {increasing, decreasing, last edge, maxedge} array<int, 4> ret = {1, 1, -1, -1}; rep(i, 0, mxlog){ if((d>>i) & 1){ combine(ret[0], dp[v][i].incr); combine(ret[1], dp[v][i].decr); ret[3] = max(ret[3], dp[v][i].maxedge); ret[2] = dp[v][i].lastval; v = bl[v][i]; } } return ret; } bool is_storing(int a, int b, int endtime){ // is a storing b <=> increasing path from b->a if(a==b) return 1; int lca = LCA(a, b); // pr(a, b, lca) if(a==lca){ auto [increasing, decreasing, lastedge, mxedge] = lift(b, dep[b]-dep[lca]); if(increasing && mxedge<endtime) return 1; } else if(b==lca){ auto [increasing, decreasing, lastedge, mxedge] = lift(a, dep[a]-dep[lca]); // pr(increasing, decreasing, lastedge, mxedge, endtime) if(decreasing && mxedge<endtime) return 1; } else{ auto [iB, dB, lastedgeB, mxB] = lift(b, dep[b]-dep[lca]); auto [iA, dA, lastedgeA, mxA] = lift(a, dep[a]-dep[lca]); if(iB && dA && lastedgeB<lastedgeA && max(mxA, mxB)<=endtime) return 1; } return 0; } signed main(){ cin.tie(0)->sync_with_stdio(0); cin>>n>>q; int timer=0; vo<array<int, 3>> queries; rep(i, 0, n+q-1){ char t; int a, b; cin>>t; if(t=='S'){ cin>>a>>b; a--, b--; adj[a].pb({b, timer}); adj[b].pb({a, timer}); } else if(t=='Q'){ cin>>a>>b; a--, b--; //does a store b, queries.pb({a, b, timer}); } else{ cin>>a; a--; queries.pb({-1, a, timer}); } timer++; } dfs(0, 0, 0, -1); for(auto [a, b, tme]: queries){ if(a==-1) cout << "1\n"; else cout << (is_storing(a, b, tme) ? "yes" : "no") << "\n"; } } /* to find if path from node to ancestor is increasing, store farthest increase upwards from each node. easily precomputed with dfs storing in binary lifting is more brain power 4 3 S 3 4 S 1 3 Q 4 3 S 1 2 Q 2 4 Q 4 2 */
#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...
#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...