【HDU5735 2016 Multi-University Training Contest 2B】【暴力做法 + 折半法】Born Slippy 祖先鏈的最大運算權值
Born Slippy
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1049 Accepted Submission(s): 307
Problem Description
Professor Zhang has a rooted tree, whose vertices are conveniently labeled by 1,2,...,n. And the i-th
vertex is assigned with weight w_i.
For each s \in \{1,2,...,n\}, Professor Zhang wants find a sequence of vertices v_1,v_2,...,v_m such that:
1. v_1=s and v_i is the ancestor of v_{i-1} (1 < i \le m).
2. the value f(s)=w_{v_1}+\sum\limits_{i=2}^{m}w_{v_i} \text{ opt } w_{v_{i-1}} is maximum. Operation x \text{ opt } y denotes bitwise AND, OR or XOR operation of two numbers.
For each s \in \{1,2,...,n\}, Professor Zhang wants find a sequence of vertices v_1,v_2,...,v_m such that:
1. v_1=s and v_i is the ancestor of v_{i-1} (1 < i \le m).
2. the value f(s)=w_{v_1}+\sum\limits_{i=2}^{m}w_{v_i} \text{ opt } w_{v_{i-1}} is maximum. Operation x \text{ opt } y denotes bitwise AND, OR or XOR operation of two numbers.
Input
There are multiple test cases. The first line of input contains an integer T,
indicating the number of test cases. For each test case:
The first line contains an integer n and a string opt (2 \le n \le 2^{16}, opt \in \{\text{AND}, \text{OR}, \text{XOR}\}) -- the number of vertices and the operation. The second line contains n integers w_1,w_2,...,w_n (0 \le w_i < 2^{16}). The thrid line contain n-1 integers f_2,f_3,...,f_n (1 \le f_i < i), where f_i is the father of vertex i.
There are about 300 test cases and the sum of n in all the test cases is no more than 10^6.
The first line contains an integer n and a string opt (2 \le n \le 2^{16}, opt \in \{\text{AND}, \text{OR}, \text{XOR}\}) -- the number of vertices and the operation. The second line contains n integers w_1,w_2,...,w_n (0 \le w_i < 2^{16}). The thrid line contain n-1 integers f_2,f_3,...,f_n (1 \le f_i < i), where f_i is the father of vertex i.
There are about 300 test cases and the sum of n in all the test cases is no more than 10^6.
Output
For each test case, output an integer S=(\sum\limits_{i=1}^{n}{i \cdot f(i)}) \text{ mod } (10^9 + 7).
Sample Input
3
5 AND
5 4 3 2 1
1 2 2 4
5 XOR
5 4 3 2 1
1 2 2 4
5 OR
5 4 3 2 1
1 2 2 4
Sample Output
91
139
195
Author
zimpha
Source
【HDU5735 2016 Multi-University Training Contest 2B】【暴力做法】Born Slippy 祖先鏈的最大運算權值
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = (1 << 16) + 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int casenum, casei;
int n; char s[10];
int w[N], g[N];
vector<int>a[N];
int op(int x, int y)
{
if (s[0] == 'X')return x ^ y;
if (s[0] == 'A')return x & y;
if (s[0] == 'O')return x | y;
}
LL dv[N]; //記錄某一深度節點最優前導值
LL dw[N]; //記錄某一深度節點的自值
LL ANS;
void dfs(int x, int fa, int dep)
{
dv[dep] = 0;
for (int i = max(1, dep - 16); i < dep; ++i)
{
gmax(dv[dep], dv[i] + op(w[x], dw[i]));
}
dv[dep];
dw[dep] = w[x];
ANS += (LL)x * (dv[dep] + w[x]);
for (int i = a[x].size() - 1; ~i; --i)
{
int y = a[x][i];
if (y == fa)continue;
dfs(y, x, dep + 1);
}
}
int main()
{
scanf("%d", &casenum);
for (casei = 1; casei <= casenum; ++casei)
{
scanf("%d", &n); scanf("%s", s);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &w[i]);
a[i].clear();
}
for (int i = 2; i <= n; ++i)
{
int x; scanf("%d", &x);
a[x].push_back(i);
}
ANS = 0;
dfs(1, 0, 1);
printf("%lld\n", ANS%Z);
}
return 0;
}
/*
【trick&&吐槽】
媽蛋
大力出奇跡
竟然因為卡題讓自己沒時間大力!
渾身難受。
讀錯題了——
ancestor是祖先而不一定是父節點。
【題意】
有n(2^16)個點。
每個點都有一個權值,
它們呈現出一棵樹的形態。
我們想對於每一個節點s(s∈[1,n])
找到一個序列v1,v2,...,vm,
使得——
1,v[1]=s
2,v[i]是v[i-1]的父節點
3,f(s)=w[v1] + w[vi] opt w[vi-1]
【型別】
暴力
【分析】
這道題雖然我們很容易構造卡掉暴力的資料
但是出題人zimpha太懶了,資料都是隨機的。
在這種情況下,每個節點以距離他最近的16個祖先為前驅更新答案,這道題就可以AC啦。
不過正解是——
用f[i][j]表示,在該節點的低8位為j,且其祖先節點的高8位為i的情況下,其所能獲得的最大前驅狀態值。
那麼,對於每個節點,假設其高8位為a,低8位為b,
我們列舉其祖先節點的前8位i,就可以通過f[i][b]得到該點的最優狀態值。
然後我們再更新f[a][0~255]
【時間複雜度&&優化】
O(暴力) -> O(n * 2^8)
*/
【HDU5735 2016 Multi-University Training Contest 2B】【折半預處理做法】Born Slippy 祖先鏈的最大運算權值
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = (1 << 16) + 10, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int casenum, casei;
int n; char s[10];
int w[N];
vector<int>e[N];
int op(int x, int y)
{
if (s[0] == 'X')return x ^ y;
if (s[0] == 'A')return x & y;
if (s[0] == 'O')return x | y;
}
LL f[256][256]; //f[i][j]表示其後八位為j,其祖先的前8位為i的條件下,其所能獲得的最優後8位的權值
LL tmp[N][256]; //tmp[i][j]用於暫存"在節點i,狀態j"對其子孫的影響生效前的f[w[x]前8位][sta]
LL ANS;
void dfs(int x, int fa)
{
int a = w[x] >> 8;
int b = w[x] & 255;
LL val = 0;
for (int i = 0; i < 256; ++i)
{
gmax(val, f[i][b] + (op(i, a) << 8));
}
ANS += x* (val + w[x]);
MC(tmp[x], f[a]);
for (int i = 0; i < 256; ++i)
{
gmax(f[a][i], val + op(b, i));
}
for (int i = e[x].size() - 1; ~i; --i)
{
int y = e[x][i];
if (y != fa)dfs(y, x);
}
MC(f[a], tmp[x]);
}
int main()
{
scanf("%d", &casenum);
for (casei = 1; casei <= casenum; ++casei)
{
scanf("%d", &n); scanf("%s", s);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &w[i]);
e[i].clear();
}
for (int i = 2; i <= n; ++i)
{
int x; scanf("%d", &x);
e[x].push_back(i);
}
MS(f, -63);
ANS = 0;
dfs(1, 0);
printf("%lld\n", ANS%Z);
}
return 0;
}
/*
【trick&&吐槽】
媽蛋
大力出奇跡
竟然因為卡題讓自己沒時間大力!
渾身難受。
讀錯題了——
ancestor是祖先而不一定是父節點。
注意,這題的答案,在不取模的條件下,最多為——
2^16*2^16,是會爆int的。
【題意】
有n(2^16)個點。
每個點都有一個權值,
它們呈現出一棵樹的形態。
我們想對於每一個節點s(s∈[1,n])
找到一個序列v1,v2,...,vm,
使得——
1,v[1]=s
2,v[i]是v[i-1]的父節點
3,f(s)=w[v1] + w[vi] opt w[vi-1]
【型別】
暴力
【分析】
這道題雖然我們很容易構造卡掉暴力的資料
但是出題人zimpha太懶了,資料都是隨機的。
在這種情況下,每個節點以距離他最近的16個祖先為前驅更新答案,這道題就可以AC啦。
不過正解是——
用f[i][j]表示,在該節點的低8位為j,且其祖先節點的高8位為i的情況下,其所能獲得的最大前驅狀態值。
那麼,對於每個節點,假設其高8位為a,低8位為b,
我們列舉其祖先節點的前8位i,就可以通過f[i][b]得到該點的最優狀態值。
然後我們再更新f[a][0~255]
【時間複雜度&&優化】
O(暴力) -> O(n * 2^8)
*/
相關文章
- HDU5735 : Born Slippy
- 2018 Multi-University Training Contest 3 - HDU ContestAI
- HDU-2016 Multi-University Training Contest 3-Sqrt Bo-大數開方AI
- HDU 6039 Gear Up(2017 Multi-University Training Contest 1)AI
- HDU 5235 Friends (2015 Multi-University Training Contest 2 搜尋+剪枝)AI
- 2018 Multi-University Training Contest 9----hdu 6415 Rikka with Nash EquilibriumAIUI
- 【HDU5734 2016 Multi-University Training Contest 2A】【公式代入推導】Acperience n維向量各有加減最小模長AI公式
- 【HDU5738 2016 Multi-University Training Contest 2E】【平面點數計數 共線判定】Eureka 平面有多少個集合滿足貢獻AI
- SDUST OJ 時間類的加、減法賦值運算賦值
- 區塊鏈最大的價值是什麼?區塊鏈
- 【填算符】(log 值域的做法)
- fd最大值和限制 linux 下 file-max 的最大值計算方法Linux
- 熵權(值)法計算權重原理解釋&綜合得分縱向對比熵
- SCSS 顏色值運算CSS
- SHELL之數值運算
- python中的Boolean運算和真假值PythonBoolean
- 計算機系統002 – 數值運算計算機
- 計算機系統002 - 數值運算計算機
- php鏈式操作實現四則鏈式運算PHP
- P8025 【樹鏈剖分求祖先】
- The 2024 Hunan Multi-School Programming Training Contest, Round 4NaNAI
- 關於int型別數值的運算問題型別
- 小白必看的python中的Bool運算和真假值Python
- 【Mysql學習】算術運算及字串,數值函式MySql字串函式
- 【Mysql 學習】算術運算及字串,數值函式MySql字串函式
- 圖解計算機中的數值範圍和浮點運算圖解計算機
- 8.Golang中的運算子-算術運算子、關係運算子、邏輯運算子、賦值運算子Golang賦值
- 折半查詢法的平均查詢長度(成功/失敗)
- MapReduce程式設計基礎(二)——數值概要(計算最大值、最小值、平均值)程式設計
- Python學習-算術運算子,賦值運算子和複合運算子Python賦值
- Flink 運算元鏈可以合併的原始碼分析原始碼
- oracle timestamp的最大值Oracle
- 微軟就版權問題猛烈抨擊谷歌 稱其做法是侵權微軟谷歌
- Git回滾程式碼暴力法Git
- 你真的知道計算機是如何進行減法運算的嗎?計算機
- [劍指offer題解][Java]佇列的最大值/滑動視窗的最大值Java佇列
- java中與運算,或運算,異或運算,取反運算Java
- 最大值減不為0的最小值