HAOI2015 泛做
T1
有一棵点数为N的树,树边有边权。给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间的距离的和的受益。问受益最大值是多少。N,K<=2000
这个树形dp不是很好想...因为贡献十分混乱...
题解十分神奇...我们记f[i][j]为i的子树有j个黑点的最大权值。
注意直接dp十分蛋疼,这个权值指的是,这个子树内部的贡献,以及i与父亲之间的边对答案的贡献(比如这条边对黑点对距离和的贡献就是子树内部的黑点数*子树外部的黑点数*这条边的权值)。
这个转移就是正常的子树合并...似乎子树合并的题目这个trick十分有用啊...
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
typedef double ld;
typedef vector<int> vi;
#define fi first
#define se second
#define fe first
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
#define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
#define es(x,e) (int e=fst[x];e;e=nxt[e])
#define cif(x) if(x) continue
#define VIZ {printf("digraph G{\n"); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;\n",i,vb[e]); puts("}");}
#define TIMER cerr<<clock()<<"ms\n"
#define gmax(a,b) if((a)<(b)) (a)=(b);
#define gmin(a,b) if((a)>(b)) (a)=(b);
#define SZ 666666
Edgc
int n,k,sz[SZ];
ll dp[2333][2333],tmp[2333];
void dfs(int x,int f=0,int fv=0)
{
int cs=1;
for es(x,e)
{
int b=vb[e]; cif(b==f);
dfs(b,x,vc[e]);
int cc=cs+sz[b];
for(int i=0;i<=min(cc,k);i++) tmp[i]=0;
for(int i=0;i<=cs&&i<=k;i++)
{
for(int j=0;j<=sz[b]&&j<=k;j++)
{
if(i+j>k) continue;
gmax(tmp[i+j],dp[x][i]+dp[b][j]);
}
}
for(int i=0;i<=min(cc,k);i++) dp[x][i]=tmp[i];
cs=cc;
}
sz[x]=cs;
for(int i=0;i<=cs&&i<=k;i++)
{
if(cs+(k-i)>n)
{
dp[x][i]=-2147400000; continue;
}
//xblack=i xwhite=cs-i
//wblack=k-i wwhite=n-cs-(k-i)
dp[x][i]+=(ll)i*(k-i)*fv;
dp[x][i]+=(ll)(cs-i)*(n-cs-(k-i))*fv;
}
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
adde(a,b,c);
}
dfs(1);
cout<<dp[1][k]<<"\n";
}
T2
链剖裸题就不说了...
似乎有两遍dfs序的做法写了写没调出来...
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define SZ 666666
typedef long long ll;
ll a1[210001],a2[210001];
ll qzh(int r)
{
ll s1=0,s2=0;
for(int i=r;i>=1;i-=i&-i) s1+=a1[i], s2+=a2[i];
return (r+1)*s1-s2;
}
ll sum(int l,int r)
{
return qzh(r)-qzh(l-1);
}
void edt(ll a,ll s1)
{
ll s2=a*s1;
for(;a<=210000;a+=a&-a) a1[a]+=s1, a2[a]+=s2;
}
void edt(int l,int r,ll a) {edt(l,a); edt(r+1,-a);}
namespace lct
{
#define SZ 666666
int n,S=0,ns[SZ],fs[SZ],ss[SZ],fa[SZ],siz[SZ],ws[SZ],dep[SZ],fe[SZ],top[SZ],X=0,ls[SZ];
void ad_de(int x,int y)
{
++S; ns[S]=fs[x]; fs[x]=S; ss[S]=y;
}
void adde(int x,int y) {ad_de(x,y); ad_de(y,x);}
void dfs1(int cur)
{
siz[cur]=1; ws[cur]=0;
int csc=-233;
for(int x=fs[cur];x;x=ns[x])
{
int c=ss[x];
if(c==fa[cur]) continue;
fa[c]=cur;
dep[c]=dep[cur]+1;
dfs1(c);
if(siz[c]>csc) csc=siz[c], ws[cur]=c;
siz[cur]+=siz[c];
}
}
void dfs2(int cur,int tp)
{
fe[cur]=++X; top[cur]=tp;
if(ws[cur]) dfs2(ws[cur],tp);
for(int x=fs[cur];x;x=ns[x])
{
int c=ss[x];
if(c!=ws[cur]&&c!=fa[cur]) dfs2(c,c);
}
ls[cur]=X;
}
void s1(int cur,int V)
{
edt(fe[cur],ls[cur],V);
}
ll s2(int x)
{
int u=1,v=x; ll ans=0;
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(dep[f1]<dep[f2]) swap(f1,f2), swap(u,v);
ans+=sum(fe[f1],fe[u]);
u=fa[f1]; f1=top[u];
}
if(dep[u]>dep[v]) swap(u,v);
ans+=sum(fe[u],fe[v]);
return ans;
}
}
int qq[233333];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",qq+i);
}
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
lct::adde(a,b);
}
lct::dfs1(1); lct::dfs2(1,1);
for(int i=1;i<=n;i++) edt(lct::fe[i],lct::fe[i],qq[i]);
for(int i=1;i<=m;i++)
{
int p; scanf("%d",&p);
if(p==1)
{
int x,a; scanf("%d%d",&x,&a);
edt(lct::fe[x],lct::fe[x],a);
}
else if(p==2)
{
int x,a; scanf("%d%d",&x,&a);
lct::s1(x,a);
}
else
{
int x; scanf("%d",&x);
printf("%lld\n",lct::s2(x));
}
}
}
T3
这个sg题真是感人至深啊...
参考链接 http://blog.csdn.net/lych_cys/article/details/50896005
首先我们可以发现问题可以转化为存在若干白点,然后将所有点翻转成黑点,先全部翻转的为胜。因为如果从黑点开始翻转后手可以翻过来...
那么我们就可以假装只有一个白点,然后把sg值异或在一起。
算一下sg,可以发现一个白点i可以转移到2i,2i、3i,2i、3i、4i...
那就是说sg[i]=mex{sg[i]^sg[2i],sg[i]^sg[2i]^sg[3i]...}
经过仔细观察(归纳证明)可以发现sg[i]只与n/i有关。
那么我们就可以暴力像莫比乌斯反演那样做,预处理时大模拟显然是不超过O(n)的,对于<=根号n的我们直接存,>根号n的就用n除一下再存。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
typedef double ld;
typedef vector<int> vi;
#define fi first
#define se second
#define fe first
#define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
#define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
#define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
#define es(x,e) (int e=fst[x];e;e=nxt[e])
#define VIZ {printf("digraph G{\n"); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;\n",i,vb[e]); puts("}");}
#ifdef LOCAL
#define TIMER cerr<<clock()<<"ms\n"
#else
#define TIMER
#endif
#define SZ 666666
int nxt(int x,int n)
{
if(x==n) return n+1;
return n/(n/(x+1)); //end
}
int n,k,sg[SZ],fsg[SZ],Q,tmp[SZ];
int main()
{
scanf("%d%d",&n,&k); Q=sqrt(n)+1;
for(int i=1;i<=n;i=nxt(i,n))
{
int cur=0; tmp[cur]=i;
for(int j=2;j<=i;j=nxt(j,i))
{
int t=i/j,p=(t<=Q)?sg[t]:fsg[n/t];
tmp[cur^p]=i;
if((i/t-i/(t+1))&1) cur^=p;
}
cur=0;
while(tmp[cur]==i) ++cur;
if(i<=Q) sg[i]=cur;
else fsg[n/i]=cur;
}
while(k--)
{
int ans=0,m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int x; scanf("%d",&x);
int t=n/x; ans^=(t<=Q)?sg[t]:fsg[n/t];
}
if(ans) puts("Yes"); else puts("No");
}
}
HAOI2015 泛做的更多相关文章
- codeforces泛做..
前面说点什么.. 为了完成日常积累,傻逼呵呵的我决定来一发codeforces 挑水题 泛做.. 嗯对,就是泛做.. 主要就是把codeforces Div.1的ABCD都尝试一下吧0.0.. 挖坑0 ...
- 学记笔记 $\times$ 巩固 · 期望泛做$Junior$
最近泛做了期望的相关题目,大概\(Luogu\)上提供的比较简单的题都做了吧\(233\) 好吧其实是好几天之前做的了,不过因为太颓废一直没有整理-- \(Task1\) 期望的定义 在概率论和统计学 ...
- 历年NOIP水题泛做
快noip了就乱做一下历年的noip题目咯.. noip2014 飞扬的小鸟 其实这道题并不是很难,但是就有点难搞 听说男神错了一个小时.. 就是$f_{i,j}$表示在第$i$个位置高度为$j$的时 ...
- LCT裸题泛做
①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...
- 基尔霍夫矩阵题目泛做(AD第二轮)
题目1: SPOJ 2832 题目大意: 求一个矩阵行列式模一个数P后的值.p不一定是质数. 算法讨论: 因为有除法而且p不一定是质数,不一定有逆元,所以我们用辗转相除法. #include < ...
- 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做
题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...
- FFT与多项式、生成函数题目泛做
题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 #include <cstdlib> #include <iostream> #include <algorit ...
- 二维计算几何基础题目泛做(SYX第一轮)
题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...
- 生成树题目泛做(AD第二轮)
题目1: NOI2014 魔法森林 LCT维护MST.解题报告见LOFTER #include <cstdio> #include <iostream> #include &l ...
随机推荐
- 转载:《TypeScript 中文入门教程》 6、命名空间
版权 文章转载自:https://github.com/zhongsp 建议您直接跳转到上面的网址查看最新版本. 关于术语的一点说明: 请务必注意一点,TypeScript 1.5里术语名已经发生了变 ...
- 【JAVA并发编程实战】8、锁顺序死锁
package cn.study.concurrency.ch10; public class Account { private String staffAccount; //账号 private ...
- JavaScript闭包理解【关键字:普通函数、闭包、解决获取元素标签索引】
以前总觉得闭包很抽象,很难理解,所以百度一下"闭包"概览,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的 ...
- JavaScript调试 - debugger语句
语法: debugger 作用: 启动调试器 备注: 1. 可以将debugger语句放在过程的任何地方以中止执行.2. 使用debugger语句类似于在代码中设置断点. 3. debugger语句中 ...
- Google LOGO现代舞舞蹈动画
效果预览:http://hovertree.com/texiao/js/5.htm 截图: HTML文件代码: <!DOCTYPE html> <html xmlns="h ...
- JS+HTML5的Canvas画图模拟太阳系运转
查看效果:http://hovertree.com/texiao/html5/9.htm 地球自传 http://hovertree.com/texiao/html5/8.htm 代码如下: < ...
- javascript中的prototype和constructor
构造函数 我们知道,ECMAScript5中的Object.Array.Date.RegExp.Function等引用类型都是基于构造函数的,他们本身就是ECMAScript5原生的构造函数.比如,我 ...
- HotApp小程序统计之如何接入
1.统计接入留存说明 更详细的说明,可以查看官网的文档 https://weixin.hotapp.cn/document 统计接入流程只需要4步 (1)注册账号 打开http://weixin.h ...
- [css]我要用css画幅画(九) - Apple Logo
接着之前的[css]我要用css画幅画(八) - Hello Kitty,这次画的是苹果公司的logo 这次打算将分析和实现步骤尽量详细的说一说. 其实之前的也打算详细讲分析和设计过程,不过之前的图比 ...
- Vmware虚拟机进入BIOS方法
在VMware里面如何进入BIOS是个头疼的问题,因为启动界面一闪而过(下面两个图如果不设置bios.bootDelay,基本上很难抓到),即使你狂按F2或ESC键(ESC: 调整启动顺序;F2: 进 ...