HourRank 19
https://www.hackerrank.com/contests/hourrank-19/challenges
第一题略。
第二题是nim博弈,问删掉一个区间的石子,使得先手败的方案有几种,明显维护前缀异或,然后一直加方案数就好了
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <vector> #include <time.h> #include <string> #include <stack> #include <set> #include <map> #include <iostream> #include <bitset> #include <algorithm> using namespace std; #define MP make_pair #define rep(i,n) for(int i = 0; i < (n); i++) #define rep1(i,n) for(int i = 1; i <= (n); i++) #define PB push_back #define mst(a,b) memset((a),(b),sizeof(a)) typedef long long LL; typedef unsigned long long uLL; typedef pair<int, int> Pii; typedef vector<int> Vi; typedef vector<Pii> Vii; const int inf = 0x3f3f3f3f; const LL INF = (1uLL << 63) - 1; const LL mod = 1000000007; const int N = 5e4 + 5; const double Pi = acos(-1.0); const int maxn = 5e5 + 5; int num[maxn]; map<int,int>cnt; int main() { #ifdef local freopen("in", "r", stdin); //freopen("w","w",stdout); #endif ios::sync_with_stdio(0); cin.tie(); int n; cin>>n; int s = 0; int res = 0; LL ans = 0; cnt[0]++; rep(i,n)cin>>num[i],res^=num[i]; rep(i,n){ s ^= num[i]; ans += cnt[s^res]; cnt[s]++; } cout<<ans<<endl; }
第三题Maximal Tree Diameter
题意:
选择一条边把这棵树分开,然后任选两个顶点再把这两棵树合并,使得新合成的树直径最长。
做法:
我们先树dp求出dp[u][(0,2)]分别表示这个点往下的三个最长次长第三长的路径,然后再求fu[u]表示从u这个点出发到达往父亲那条路径走的最长路径。。这里很像hdu2196的一个操作,然后我们在第一次dp时,顺便求出subtree[u]表示,u的子树的最长直径(不一定包括u),有了上面的,我们就可以维护答案了,当跑到一个点u,它的一个儿子是v时,当我们选择拆这条边我们怎么能取得最优解呢,明显,我们需要subtree[v] + dp[v][0] + max(dp[v][1],fu[v]).但是这条边很有可能是就是u的最长路径,或者次长,或者其他,所以我们才需要更新其他的一些信息。
比赛的时候没考虑到第三长的边= = 感觉很亏。
#include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <vector> #include <time.h> #include <string> #include <stack> #include <set> #include <map> #include <iostream> #include <bitset> #include <algorithm> using namespace std; #define MP make_pair #define rep(i,n) for(int i = 0; i < (n); i++) #define rep1(i,n) for(int i = 1; i <= (n); i++) #define PB push_back #define mst(a,b) memset((a),(b),sizeof(a)) typedef long long LL; typedef unsigned long long uLL; typedef pair<int, int> Pii; typedef vector<int> Vi; typedef vector<Pii> Vii; const int inf = 0x3f3f3f3f; const LL INF = (1uLL << 63) - 1; const LL mod = 1000000007; const int N = 5e4 + 5; const double Pi = acos(-1.0); const int maxn = 5e5 + 5; int dp[maxn][3]; Vi edge[maxn]; int dostree[maxn]; int fu[maxn]; void um(int &a,int b){ if(a < b)a = b; } void sfs1(int u, int fa) { dostree[u] = dp[u][0] = dp[u][1] = dp[u][2] = 0; for(int v : edge[u]) { if(v == fa)continue; sfs1(v, u); um(dostree[u],dostree[v]); if(dp[v][0] + 1 >= dp[u][0]){ dp[u][2] = dp[u][1]; dp[u][1] = dp[u][0]; dp[u][0] = dp[v][0] + 1; }else if(dp[v][0] + 1 >= dp[u][1]){ dp[u][2] = dp[u][1]; dp[u][1] = dp[v][0] + 1; }else if(dp[v][0] + 1 >= dp[u][2]){ dp[u][2] = dp[v][0] + 1; } } um(dostree[u],dp[u][0] + dp[u][1]); } void sfs2(int u,int fa){ for(int v : edge[u]){ if(v == fa)continue; fu[v] = max(fu[u],dp[v][0] + 1 == dp[u][0]? dp[u][1] : dp[u][0]) + 1; sfs2(v,u); } } int res = 0; void sfs3(int u,int fa){ for(int v : edge[u]){ if(v == fa)continue; if(dp[v][0] + 1 == dp[u][0]){ um(res,dostree[v] + 1 + dp[u][1] + dp[u][2]); um(res,dostree[v] + 1 + dp[u][1] + fu[u]); }else if(dp[v][0] + 1 == dp[u][1]){ um(res,dostree[v] + 1 + dp[u][0] + dp[u][2]); um(res,dostree[v] + 1 + dp[u][0] + fu[u]); }else { um(res,dostree[v] + 1 + dp[u][0] + dp[u][1]); um(res,dostree[v] + 1 + dp[u][0] + fu[u]); } sfs3(v,u); } } int main() { #ifdef local freopen("in", "r", stdin); //freopen("w","w",stdout); #endif ios::sync_with_stdio(0); cin.tie(); int n; cin >> n; rep(i, n - 1) { int u, v; cin >> u >> v; edge[u].PB(v); edge[v].PB(u); } sfs1(1,0); sfs2(1,0); sfs3(1,0); cout<<res<<endl; }