博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
点分治练习
阅读量:4610 次
发布时间:2019-06-09

本文共 3872 字,大约阅读时间需要 12 分钟。

写下自己出错过的地方:

1, 读入$n-1$条边, 别写成REP(i,1,n)

2, 分治时, solve(rt)别写成solve(y)

3, 

 

练习1 CF 161D 

大意:给定树, 求长为k的链的个数

该题算点分入门了, 比较简单, 可以拿来练手. 当然这题$k$的范围较小, $O(nk)$的暴力dp也是能过的

 

#include 
#include
#include
#include
#define pb push_back#define REP(i,a,n) for(int i=a;i<=n;++i)using namespace std;typedef long long ll;const int N = 4e5+10, INF = 0x3f3f3f3f;int n, k, sum, rt;int maxp[N], sz[N], vis[N];int cnt[N];ll ans;vector
g[N];void getrt(int x, int fa) { sz[x]=1, maxp[x]=0; for (int y:g[x]) if (!vis[y]&&y!=fa) { getrt(y,x),sz[x]+=sz[y]; maxp[x]=max(maxp[x],sz[y]); } maxp[x]=max(maxp[x],sum-sz[x]); if (maxp[rt]>maxp[x]) rt=x;}void dfs(int x, int fa, int d, int v) { if (d>k) return; cnt[d] += v; for (int y:g[x]) if (!vis[y]&&y!=fa) dfs(y,x,d+1,v);}void dfs2(int x, int fa, int d) { if (d>k) return; ans += cnt[k-d]; for (int y:g[x]) if (!vis[y]&&y!=fa) dfs2(y,x,d+1);}void solve(int x) { vis[x]=1; dfs(x,0,0,1); ans += cnt[k]; for (int y:g[x]) if (!vis[y]) { dfs(y,x,1,-1); dfs2(y,x,1); dfs(y,x,1,1); } dfs(x,0,0,-1); for (int y:g[x]) if (!vis[y]) { maxp[rt=0]=n,sum=sz[y]; getrt(y,0), solve(rt); }}int main() { scanf("%d%d", &n, &k); REP(i,2,n) { int u, v; scanf("%d%d", &u, &v); g[u].pb(v),g[v].pb(u); } sum=maxp[0]=n, getrt(1,0),solve(rt); printf("%lld\n", ans>>1);}

 

 

练习2 POJ 1741

大意: 求树上有多少长度不超过k的链

跟上题一样, 树状数组维护一个前缀即可

 

#include 
#include
#include
#include
#define REP(i,a,n) for(int i=a;i<=n;++i)#define pb push_backusing namespace std;typedef long long ll;const int N = 4e5+10, INF = 0x3f3f3f3f;int n, k, rt, sum;struct _ {int to,w;};vector<_> g[N];ll ans;int sz[N], mx[N], vis[N];int c[N];void add(int x, int v) { for (++x; x<=k+1; x+=x&-x) c[x]+=v;}int qry(int x) { int r = 0; for (++x; x; x^=x&-x) r+=c[x]; return r;}void getrt(int x, int fa) { mx[x]=0,sz[x]=1; for (_ e:g[x]) if (!vis[e.to]&&e.to!=fa) { int y = e.to; getrt(y,x),sz[x]+=sz[y]; mx[x]=max(mx[x],sz[y]); } mx[x]=max(mx[x],sum-sz[x]); if (mx[x]
k) return; add(w,v); for (_ e:g[x]) if (!vis[e.to]&&e.to!=fa) { int y = e.to; dfs(y,x,w+e.w,v); }}void dfs2(int x, int fa, int w) { if (w>k) return; ans += qry(k-w); for (_ e:g[x]) if (!vis[e.to]&&e.to!=fa) { int y = e.to; dfs2(y,x,w+e.w); }}void solve(int x) { vis[x]=1; dfs(x,0,0,1); ans += qry(k)-qry(0); for (_ e:g[x]) if (!vis[e.to]) { int y = e.to; dfs(y,x,e.w,-1); dfs2(y,x,e.w); dfs(y,x,e.w,1); } dfs(x,0,0,-1); for (_ e:g[x]) if (!vis[e.to]) { int y = e.to; mx[rt=0]=n,sum=sz[y]; getrt(y,0),solve(rt); }}int main() { for (; scanf("%d%d", &n, &k),n||k; ) { REP(i,1,n) g[i].clear(); REP(i,2,n) { int u, v, w; scanf("%d%d%d", &u, &v, &w); g[u].pb({v,w}); g[v].pb({u,w}); } sum=mx[0]=n,getrt(1,0),solve(rt); printf("%lld\n", ans>>1); }}

 

 

 

 

 

练习3 CF 914E

大意: 给定树,每个点上有个字母a-t之一, 对于每个点, 求有多少经过该点的链使得: 链上字母的某一个排列是回文的

 

注意到回文等价于出现奇数次的字母最多只有一个, 状压一下即可

#include 
#include
#include
#include
#include
#define REP(i,a,n) for(int i=a;i<=n;++i)#define pb push_backusing namespace std;typedef long long ll;const int N = 2e5+10, INF = 0x3f3f3f3f;int n, sum, rt;int a[N], vis[N], sz[N], maxp[N];char s[N];vector
g[N];ll ans[N], cnt[1<<20];void getrt(int x, int fa) { sz[x]=1, maxp[x]=0; for (int y:g[x]) if (!vis[y]&&y!=fa) { getrt(y,x),sz[x]+=sz[y]; maxp[x]=max(maxp[x],sz[y]); } maxp[x]=max(maxp[x],sum-sz[x]); if (maxp[rt]>maxp[x]) rt=x;}void dfs(int x, int fa, int s, int v) { s ^= a[x], cnt[s] += v; for (int y:g[x]) if (!vis[y]&&y!=fa) dfs(y,x,s,v);}ll calc(int x, int fa, int s) { s ^= a[x]; ll r = cnt[s]; REP(i,0,19) r += cnt[s^1<

 

 

 

转载于:https://www.cnblogs.com/uid001/p/10403080.html

你可能感兴趣的文章
CSS3 新属性兼容性测试
查看>>
js闭包
查看>>
Oralce导入数据库出现某一列的值太大
查看>>
Union和Union All 的区别
查看>>
sql server 2005函数
查看>>
innotop
查看>>
jmeter 取样器--http请求详解
查看>>
【转载】Understanding the Objective-C Runtime
查看>>
aabb碰撞检测
查看>>
Xshell连接Linux
查看>>
20180530
查看>>
项目复审——Alpha阶段
查看>>
React Native Windows下环境安装(一)
查看>>
文本CSS
查看>>
JDK1.7新特性,语言篇
查看>>
javaScript判断手机型号
查看>>
应用程序设计:图书管理系统模板(链表+文件)
查看>>
遗传算法学习--多目标优化中的遗传算法
查看>>
Git的安装和使用教程详解
查看>>
lsof命令详解
查看>>