Problem B. Appleman and Tree
Brief description:
给定一棵有根树,每个点有黑白两种颜色,问有多少种树的划分方案,
使得每个联通块中都恰好有一个黑色结点。
Analysis:
树 DP,子树合并。设:
- f[u] 表示以 u 为根的子树中,经过划分过后,与 u 相连的联通块恰好包含一个黑色结点的方案数。
- g[u] 表示以 u 为根的子树中,经过划分过后,与 u 相连的联通块。。。不包含黑色结点的方案数。
转移讨论是否切割 (u, v) 这条边即可。
void dfs(int u = 0){
ECH(it, adj[u]){
dfs(v);
f[u] = f[u]*(f[v]+g[v]) + g[u]*f[v];
g[u] *= (f[v]+g[v]);
}
}
http://codeforces.com/contest/461/submission/7612452
C:
Brief description:
给定一张纸,支持两个操作:。
。。沿某个位置对折。
。。询问某个区间纸张的体积。
Analysis:
树状数组。对于折叠操作,我们总是枚举较短的一部分,加到较长的一部分中去。
每个位置只会用来合并一次。总复杂度 O(nlogn)。。
具体说来我们需要记录 ll, rr, rev 三个值。。
分别表示两侧的偏移,以及是否翻转。。。
//}/* .................................................................................................................................. */
const int N = int(1e5) + 9;
namespace BIT{
int C[N], n;
void Add(int x, int d){
for (;x<=n;x+=low_bit(x)) C[x] += d;
}
int Sum(int x){
int z=0;for (;x;x^=low_bit(x)) z += C[x];
return z;
}
int Sum(int l, int r){
return Sum(r) - Sum(l-1);
}
int At(int x){
int z=C[x],p=low_bit(x);for (--x;x&&low_bit(x)<p;x^=low_bit(x)) z -= C[x];
return z;
}
} using namespace BIT;
bool rev; int ll, rr;
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
#define len (rr-ll+1)
#define pp (2*p)
REP_1_C(i, RD(n)) Add(i, 1); ll=1,rr=n;rev=0; Rush{
if (RD()==1){ // Fold
int p; RD(p); if (pp<=len){
if (!rev){
REP_1(i, p) Add(ll+pp-i, At(ll+i-1)); ll += p;
}
else{
REP_1(i, p) Add(rr-pp+i, At(rr-i+1)); rr -= p;
}
}
else{
rev ^= 1; p=len-p; if (!rev){
REP_1(i, p) Add(ll+pp-i, At(ll+i-1)); ll += p;
}
else{
REP_1(i, p) Add(rr-pp+i , At(rr-i+1)); rr -= p;
}
}
}
else{ // Query
int a, b; RD(a, b);
OT(rev ? Sum(rr-b+1, rr-a) : Sum(ll+a, ll+b-1));
}
}
}
http://codeforces.com/contest/461/submission/7612792
D:
1 2 3 12 23 2 123 2 23 12 3 2 1
1 2 1 12 2 12 12 2 12 1 2 1
const int N = int(2e6) + 9;
int n;
namespace DSU{ // Disjoint Set Union
int P[N], R[N];
inline void Make(int x){
P[x] = x, R[x] = 0;
}
inline int Find(int x){
return P[x] == x ? x : P[x] = Find(P[x]);
}
inline void Unionn(int x, int y){
if (R[x] == R[y]) ++R[x];
else if (R[x] < R[y]) swap(x, y);
P[y] = x;
}
inline void Union(int x, int y){
int xx = Find(x), yy = Find(y);
if (xx == yy){
return;
}
else{
Unionn(xx, yy);
}
}
void Union(int x, int y, int z){
if (z) Union(x,y+n+2),Union(x+n+2,y);
else Union(x,y),Union(x+n+2,y+n+2);
}
inline void Init(int n){
REP(i, n) Make(i);
}
} using namespace DSU;
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
RD(n); Init(2*(n+2)); Rush{
int a, b; RD(a, b); int u = abs(a-b), v = n-1 - abs(a+b-n-1);
if (u > v) swap(u, v);
Union(u, v+2, RC()=='o');
}
REP(i, n+2) if (Find(i) == Find(i+n+2)){
puts("0");
return 0;
}
int rk = -2; REP(i, n+2) if (Find(i) == i) ++rk;
cout << pow(2, rk) << endl;
}
E:
dp[i][j][k]:起始i终止j需要2^k次的最短长度- –
但是 SAM 中状态太多怎么办?。。。
通过预处理出起始 x 终止 y 的最短不在 SAM 中的串。。。可以将 i, j 改成字符集。。。
External link:
http://ftiasch.github.io/blog/2014/08/27/codeforces-round-263/




Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos
