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 ...
随机推荐
- Java入门第一章
后天就是十一长假了,亲们准备好了去哪儿玩了吗? 今天有点空,就来聊聊Java吧,当然是一些Java入门知识了,网上有很多,这里我只是列举一些我自己学到的,感谢大家关注喵的博客这么久,也为大家带来点新知 ...
- Lind.DDD.Caching分布式数据集缓存介绍
回到目录 戏说当年 大叔原创的分布式数据集缓存在之前的企业级框架里介绍过,大家可以关注<我心中的核心组件(可插拔的AOP)~第二回 缓存拦截器>,而今天主要对Lind.DDD.Cachin ...
- ASP.NET Redis 开发
文件并发(日志处理)--队列--Redis+Log4Net Redis简介 Redis是一个开源的,使用C语言编写,面向“键/值”对类型数据的分布式NoSQL数据库系统,特点是高性能,持久存储,适应高 ...
- Java基础学习 -- I/O系统、流
Java类库里有四个表示流的抽象父类:InputStream.OutputStream.Reader.Writer. 其中 InputStream 和 OutputStream 是对字节进行操作的输入 ...
- RequireJS 模块的定义与加载
模块不同于传统的脚本文件,它良好地定义了一个作用域来避免全局名称空间污染.它可以显式地列出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入,而无需引用全局变量.RequireJ ...
- hibernate(1) —— 入门
hibernate框架主要是实现数据库与实体类间的映射,使的操作实体类相当与操作hibernate框架. 只要实体类写好配置文件配好,就能实现和数据库的映射,其中实体类对应表,类的属性对应数据库的表字 ...
- MyEclipse使用心得:SVN插件安装方法
1.在线安装,打开myeclipse,help--->MyEclipse Configuration Center 2.点击Add Site 打开对话框,在对话框Name输入Svn,URL中输入 ...
- 【超全整理】J2EE集成开发环境MyEclipse使用心得汇总
一.首先我们为什么需要MyEclipse? 下面允许我做一些简要的介绍: 应该大家都知道另一个MyEclipse的近亲——Eclipse的优点:免费.程序代码排版功能.有中文汉化包.可增设许多功能强大 ...
- 三种POST和GET的提交方式
向服务器提交数据有两种方式,post和get.两者的区别主要有三点,安全性.长度限制.数据结构.其中get请求安全性相比较而言较差,数据长度受浏览器地址栏限制,没有方法体.两种都是较为重要的数据提交方 ...
- FMDB第三方框架
FMDB是同AFN,SDWebImage同样好用的第三方框架,它以OC的方式封装了SQLite的C语言API,使得开发变得简单方便. 附上github链接https://github.com/ccgu ...