【題目大意】
有一棵樹,樹上一條簡單路徑(u,v)的價值定義為這條路徑的所有邊的異或和。求這些價值的第k大。
【思路】
如果我們統計根到節點u,路徑的異或和為a[u],顯然,路徑(u,v)的價值為a[u]^a[v]。問題變為了從n個數中選兩個不同的數,求異或,找第k大。因為k其實不是很大,我們可以考慮將1-max(k)的價值都找出來。用a建立tire樹,首先列舉路徑的左端點,通過tire找到乙個右端點,使得其異或值最大。把這些數加入優先佇列,顯然,這些數中,最大的那個,就是第一大的價值。然後把這個價值刪掉,通過原來的左端點,再找乙個右端點,使其異或值變成次大,並把這個值加入優先佇列。這個時候,佇列中最大的元素是第二大的價值。這樣一直找下去,就能把所有k都找到。
#pragma comment(linker, "/stack:102400000,102400000")
#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;
#define mp(x,y) make_pair((x),(y))
#define pb(x) push_back(x)
typedef __int64 ll;
//typedef unsigned __int64 ull;
/* ****************** */
const ll inf = 1ll<<55;
const double inff = 1e100;
const double eps = 1e-8;
const ll mod = 10000000007ll;
const int nn = 100010;
const int mm = 5000010;
/* ****************** */
const int limit = 59;
struct g
e[nn*2];
int p[nn], t;
struct node
bool operator<(const node &tt)const
};ll a[nn];
struct tire
}tire[nn*60];
struct q
}q[nn];
ll anss[nn];
void add(int u,int v,ll w)
void dfs(int u,int fa)
}void tire_insert(ll val,int root,int &tire_cnt)
for(i = 1; i <= n; i ++)
j = 1;
memset(anss, -1, sizeof(anss));
for(i = 1; i <= (ll)n*(n-1) && j <= m ; i ++)
if(ix.num > 1)
else
}for(i = 1; i <= m; i ++)
printf("%i64d\n", anss[i]);
}int main()
a[1] = 0;
dfs(1,-1);
scanf("%d", &m);
for(i = 1; i <= m; i ++)
sort(q+1,q+1+m);
solve(n, m);
}return 0;
}
HDU 2829 Lawrence dp 斜率優化
題意 一段直線上有n個點,每個點有乙隻價值,一條鐵路的價值等於每兩個點 可以直接或者間接相連,就是聯通路上是否有炸彈把路給炸了 積的和 思路 斜率優化 dp i j 為前i個點,炸j個線段能破壞的最大值 沒優化前的狀態轉移方程為dp i x max x 1 設計算點i時,j比k的值優,dp k x ...
hdu5976 Detachment 逆元 優化
傳送門 題意 給定乙個數x,我們可以把這個數分解成乙個乙個的小的數字a1,a2,a3 定義s a1 a2 a3 問如何分解x使得s最大,並且不能有重複的數字 思路 分解成數量多的小的數字,比分解成數量少的大的數字的乘積更大,這一點我不知道怎麼證明 並且由基本不等式我們可以知道,相等和的兩個數,越接近...
hdu2639 01揹包k優解)
沒怎麼理解題意,題意 有n件物品,揹包體積為v,給出一行價值和一行花費,求第k優解,每個物品只能取一次。思路 不考慮k優解,顯然是個簡單的01揹包,1維的陣列足夠表示。即便要求k優解,在k 30的條件下,此題再加1維也沒什麼好說的,用dp j k 表示揹包體積為j時的k優解,一開始不知道怎麼轉移,原...