Solved | Pro.ID | Title | Ratio(Accepted / Submitted) |
1001 | Rikka with Quicksort | 25.85%(38/147) | |
1002 | Rikka with Cake | 31.69%(379/1196) | |
1003 | Rikka with Mista | 5.57%(45/808) | |
1004 | Rikka with Geometric Sequence | 9.52%(2/21) | |
1005 | Rikka with Game | 35.29%(866/2454) | |
1006 | Rikka with Coin | 7.16%(358/5003) | |
1007 | Rikka with Travels | 21.46%(85/396) | |
1008 | Rikka with Stable Marriage 字典树+贪心 | 17.02%(8/47) | |
1009 | Rikka with Traffic Light | 0.00%(0/24) | |
1010 | Rikka with Defensive Line | 0.00%(0/20) | |
1011 | Rikka with Segment Tree | 39.39%(13/33) |
1007 Rikka with Travels
思路:
一棵树上最长链处理,分出两种情况,一种是(a,b)各占一个端点,还有一种情况a占整条链,b是全踩在非最长链。
#include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> #include <unordered_map> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef unsigned long long ull; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ const int maxn = 1e5+9; int n; vector<int>mp[maxn]; int vis[maxn]; int dis[maxn]; vector<int>lian; ///扣出最长链 void koulian() { for(int i=1; i<=n; i++) dis[i] = inf; dis[1] = 0; queue<int>que; que.push(1); int t = 1; while(!que.empty()) { int u = que.front(); que.pop(); if(dis[u] > dis[t])t = u; for(int v : mp[u]) { if(dis[v] > dis[u] + 1) { dis[v] = dis[u] + 1; que.push(v); } } } for(int i=1; i<=n; i++) dis[i] = inf; dis[t] = 0; que.push(t); int s = t; while(!que.empty()) { int u = que.front(); que.pop(); if(dis[u] > dis[s])s = u; for(int v:mp[u]) { if(dis[v] > dis[u] + 1) { dis[v] = dis[u] + 1; que.push(v); } } } lian.pb(s); vis[s] = 1; while(s != t) { for(int v : mp[s]) { if(dis[v] +1 == dis[s]) { s = v; lian.pb(s); vis[s] = 1; break; } } } } int dpa[maxn], dpb[maxn][2], pre[maxn]; int dppre[maxn], dpback[maxn]; ///求出以最长链上一个点为根节点的不经过最长链的最大深度 void dfs1(int u, int fa) { dpa[u] = 1; for(int v : mp[u]) { if(v == fa || vis[v]) continue; dfs1(v, u); dpa[u] = max(dpa[u], dpa[v] + 1); }} void dfs2(int u, int fa) { dpb[u][0] = dpb[u][1] = 1; ///dpb[0]表示包含根节点的最长链 ///dpb[1]表示包含根节点的次长链 pre[u] = 1; for(int v : mp[u]) { if(vis[v] || v == fa) continue; dfs2(v, u); pre[u] = max(pre[u], pre[v]); if(dpb[u][1] <= dpb[v][0] + 1){ dpb[u][1] = dpb[v][0] + 1; if(dpb[u][0] < dpb[u][1]) { swap(dpb[u][0], dpb[u][1]); } } } pre[u] = max(pre[u], dpb[u][0] + dpb[u][1] - 1); } int hei[maxn]; int main(){ int T; scanf("%d", &T); while(T--){ scanf("%d", &n); for(int i=1; i<n; i++) { int u, v; scanf("%d%d", &u, &v); mp[u].pb(v); mp[v].pb(u); } for(int i=0; i<=n; i++) vis[i] = 0, hei[i] = 0, pre[i] = 0, dppre[i] = 0,dpback[i] = 0; koulian(); for(int i=0; i<lian.size(); i++) { int v = lian[i]; dfs1(v, v); if(i)dppre[i] = max(dppre[i-1], dpa[v] + i); else dppre[i] = dpa[v]; for(int p : mp[v]) { if(vis[p]) continue; dfs2(p, p); pre[v] = max(pre[v], pre[p]); } pre[v] = max(pre[v], pre[lian[max(0, i-1)]]); } int cc = 0; for(int i=lian.size()-1; i>=0; i--) { if(i == lian.size() - 1) dpback[i] = dpa[lian[i]]; else dpback[i] = max(dpback[i+1], dpa[lian[i]] + cc); cc++; } int all = lian.size(); hei[all] = pre[lian[all-1]]; hei[pre[lian[all-1]]] = all; for(int i=lian.size() - 1; i>=1; i--) { int v = lian[i]; int a = dppre[i-1]; int b = dpback[i]; hei[a] = max(hei[a], b); hei[b] = max(hei[b], a); } ll sum = 0; int c = 0; for(int i=all; i>=1; i--) { c = max(c, hei[i]); sum = sum + c; } printf("%lld ", sum); lian.clear(); for(int i=1; i<=n; i++) mp[i].clear(); } return 0; } /* 10 9 1 2 2 3 3 4 4 5 5 8 3 6 3 7 7 9 14 1 2 2 3 3 4 4 5 5 6 6 7 3 8 3 9 4 10 4 11 11 14 5 12 5 13 = 36 */
1008 Rikka with Stable Marriage
思路:
就是字典树+贪心,和第五场那个贪心顺序反一下就行了
// #pragma GCC optimize(2) // #pragma GCC optimize(3) // #pragma GCC optimize(4) #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <bitset> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <stack> #include <cmath> #include <queue> #include <list> #include <map> #include <set> #include <cassert> // #include<bits/extc++.h> // using namespace __gnu_pbds; using namespace std; #define pb push_back #define fi first #define se second #define debug(x) cerr<<#x << " := " << x << endl; #define bug cerr<<"-----------------------"<<endl; #define FOR(a, b, c) for(int a = b; a <= c; ++ a) typedef long long ll; typedef long double ld; typedef pair<int, int> pii; typedef pair<ll, ll> pll; const int inf = 0x3f3f3f3f; const ll inff = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; template<typename T> inline T read(T&x){ x=0;int f=0;char ch=getchar(); while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x=f?-x:x; } /**********showtime************/ const int maxn = 1e5+9; int a[maxn],b[maxn]; int tot[2],rt[2]; int bz[33]; struct node{ int ch[2]; int fa; int sz; void init(int f) { ch[0] = ch[1] = 0; fa = f; sz = 0; } }tree[2][maxn * 30]; int shu[35]; void add(int p, int len, int flag) { if(len == 0){ tree[flag][p].sz++; return; } if(tree[flag][p].ch[shu[len]] == 0) { tree[flag][p].ch[shu[len]] = ++ tot[flag]; tree[flag][tot[flag]].init(p); } int nx = tree[flag][p].ch[shu[len]]; add(nx, len-1, flag); int lc = tree[flag][p].ch[0]; int rc = tree[flag][p].ch[1]; tree[flag][p].sz = tree[flag][lc].sz + tree[flag][rc].sz; } void insert(int val, int flag) { int len = 0; for(int i=0; i<=30; i++) shu[++len] = val % 2, val /= 2; add(rt[flag], 30, flag); } void display(int rt, int flag) { if(rt == 0) return ; // cout<<tree[flag][rt].sz<<endl; display(tree[flag][rt].ch[0], flag); display(tree[flag][rt].ch[1], flag); } vector<int>vec; void find(int a, int b, int cen, int val) { if(cen == 0) { vec.pb(val); tree[0][a].sz--; tree[1][b].sz--; return; } if(tree[0][tree[0][a].ch[0]].sz && tree[1][ tree[1][b].ch[1]].sz){ find(tree[0][a].ch[0], tree[1][b].ch[1], cen-1, val + bz[cen-1]); } else if(tree[0][tree[0][a].ch[1]].sz && tree[1][ tree[1][b].ch[0]].sz){ find(tree[0][a].ch[1], tree[1][b].ch[0], cen-1, val + bz[cen-1]); } else if(tree[0][ tree[0][a].ch[0] ].sz && tree[1][ tree[1][b].ch[0]].sz ) { find(tree[0][a].ch[0], tree[1][b].ch[0], cen-1, val); } else if(tree[0][ tree[0][a].ch[1] ].sz && tree[1][ tree[1][b].ch[1]].sz) { find(tree[0][a].ch[1], tree[1][b].ch[1], cen-1, val); } tree[0][a].sz = tree[0][tree[0][a].ch[0]].sz + tree[0][tree[0][a].ch[1]].sz; tree[1][b].sz = tree[1][tree[1][b].ch[0]].sz + tree[1][tree[1][b].ch[1]].sz; } int main(){ int T; scanf("%d", &T); bz[0] = 1; for(int i=1; i<=30; i++) bz[i] = 2 * bz[i-1]; while(T--) { tot[0] = tot[1] = 0; rt[0] = ++tot[0]; tree[0][rt[0]].init(0); rt[1] = ++tot[1]; tree[1][rt[1]].init(0); int n; scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]), insert(a[i], 0); for(int i=1; i<=n; i++) scanf("%d", &b[i]), insert(b[i], 1); vec.clear(); for(int i=1; i<=n; i++) { find(rt[0], rt[1], 30, 0); } ll sum = 0; for(int i=0; i<vec.size(); i++) sum += vec[i]; printf("%lld ", sum); } return 0; }