Quasi Binary Search Tree
贪心,重构二叉树,
1.如果左右子树最小节点都比当前节点大,则选择节点数少的子树当作左子树。节点数一样执行2
2.如果左子树最小节点比右子树最小节点大,则交换左右子树。
重构完成后中序遍历,标号
// // Created by liulex on 2020/7/24. // #include <bits/stdc++.h> using namespace std; #define int long long signed L[100005],R[100005]; bool vis[100005]; signed n; signed lsz[100005],rsz[100005]; signed mi[100005],f[100005],A[100005]; signed dfs(signed x) { mi[x] = 1e9; if(L[x]){ mi[x] = min(mi[x],dfs(L[x])); f[x] = -1; lsz[x] = lsz[L[x]]+1; } if(R[x]){ signed k = dfs(R[x]); if(k < mi[x]){ f[x] = 1; mi[x] = k; } rsz[x] = rsz[R[x]] + 1; } return min(mi[x],x); } void build(signed x) { if(mi[x] > x){ if(lsz[x] > rsz[x]){ swap(L[x],R[x]); } }else{ if(f[x] == 1){ swap(L[x],R[x]); } } if(L[x]){ build(L[x]);} if(R[x]){ build(R[x]);} } int cnt = 0; void traver(int x){ if(L[x]){ traver(L[x]); } A[cnt++] = x; if(R[x]) { traver(R[x]); } } int mod = 1e9 + 7; int F[100005]; void init() { F[0] = 1; for(int i = 1; i <= 100000; i++){ F[i] = (F[i-1]*233ll)%mod; } } signed main() { signed T; init(); scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i = 1; i <= n; i++){ scanf("%d%d",&L[i],&R[i]); vis[L[i]] = true; vis[R[i]] = true; } signed root = -1; for(int i = 1; i <= n; i++){ if(!vis[i]){ root = i; }else{ vis[i] = false; } } dfs(root); build(root); cnt = 1; traver(root); int ans = 0; for(int i = 1; i <= n; i++){ ans = (ans +(i^A[i])*F[A[i]]%mod)%mod; } cout<< ans << ' '; for(int i = 1; i <= n; i++){ lsz[i] = rsz[i] = mi[i] = f[i] = A[i] = 0; } } }
Diversity
树形dp,dp[x][0]表示当前节点取L[x],dp[x][1]表示当前节点取R[x]
#include <bits/stdc++.h> using namespace std; vector<int> G[100005]; int L[100005],R[100005]; long long dp[100005][2]; int n,x,y; void dfs(int x,int f) { dp[x][0] = dp[x][1] = 0; for(auto i : G[x]){ if(i != f){ dfs(i,x); dp[x][0] += max(abs(L[x]-L[i])+dp[i][0],abs(L[x]-R[i])+dp[i][1]); dp[x][1] += max(abs(R[x]-L[i])+dp[i][0],abs(R[x]-R[i])+dp[i][1]); } } } int main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i = 0; i < n - 1; i++){ scanf("%d%d",&x,&y); G[x].push_back(y); } for(int i = 1; i <= n; i++){ scanf("%d%d",&L[i],&R[i]); } dfs(1,-1); cout<<max(dp[1][0],dp[1][1])<<' '; for(int i= 1;i <= n; i++){ G[i].clear(); } } return 0; }
Transformation
打表找规律
// // Created by liulex on 2020/7/24. // #include <bits/stdc++.h> using namespace std; #define int long long int P[70]; void init() { P[0] = 1; for(int i = 1; i <= 62; i ++) { P[i] = (P[i - 1] * 2ll); } } int a,b,c,d; signed main() { init(); int T; scanf("%lld",&T); while(T--){ scanf("%lld%lld%lld%lld",&a,&b,&c,&d); if(a == b && (c != a ||d != b)){ puts("No"); }else if(a == c && b == d){ puts("Yes"); cout<<' '; }else if((c + d) &1){ puts("No"); }else if(a > b && (c < a || d > b)){ puts("No"); }else if(a < b && (d < b || c > a)){ puts("No"); }else{ int r = abs(a - b); int k = abs(c - a); if(k%r != 0){ puts("No"); }else{ k = k/r; string s = ""; if(k == 0){ }else if(k == 1){ s = 'B'; }else{ int i = 0; while(k > P[i]){ k -= P[i]; i++; } s = 'B'; while(i > 0) { if (k <= P[i] / 2) { s = 'A'+s; }else { k -= P[i]/2; s = 'B' + s; } i--; } } bool flag = (a > b); for(auto& i: s){ if(i == 'A'){ b = 2*b - a; }else{ a = 2*a - b; } } if(flag && b < d){ puts("No"); }else if((!flag) && b > d){ puts("No"); }else{ int u = b-a; int o = b; for(int i=0;i<62;i++){ if(((u > 0) && (P[i] - 1) * u + o > d)||(u < 0 &&(P[i] - 1) * u + o < d)){ puts("No"); break; }else if((P[i] - 1) * u + o == d){ for(int j = 0; j < i ; j ++){ s += 'A'; } puts("Yes"); cout<<s<<' '; break; } } } } } } }