151221 HAoi2015 总结

T1

树形dp

dp[i][j]表示以i为子树,j个黑点

每次向上枚举更新即可

复杂度O(n^2)考场上sb了被卡常,50滚粗

T2树链剖分,不说了

T3博弈论

首先搜索打表找规律

发现n/i一定时,sg一定

然后分块大法好

set

vfk未来的论文题,刚好在考前一天看过还给bzoj写了spj。。。。

http://www.cnblogs.com/gromah/p/4642344.html 快去围观大神的博客

悲剧又被卡常= =60

str

好像是矩乘来着?蒟蒻表示吓傻了

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 100000000
using namespace std;
inline void splay(ll &v){
	v=0;char c=0;ll p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
struct Edge{
	ll to,next,len;
}edge[4010];
ll dp[2005][2005];
ll size[2005];
ll n,k;
ll first[4010],Size;
void addedge(ll x,ll y,ll z){
	Size++;
	edge[Size].to=y;
	edge[Size].len=z;
	edge[Size].next=first[x];
	first[x]=Size;
}
void dfs(ll now,ll fa){
	size[now]=1;dp[now][0]=dp[now][1]=0;
	for(ll u=first[now];u;u=edge[u].next){
		if(edge[u].to==fa)continue;
		dfs(edge[u].to,now);size[now]+=size[edge[u].to];
		for(ll i=size[now];i>=0;i--){
			for(ll j=0;j<=size[edge[u].to]&&j<=i&&j<=k;j++){
				dp[now][i]=max(dp[now][i],dp[now][i-j]+dp[edge[u].to][j]+(j*(k-j)+(size[edge[u].to]-j)*(n-k-(size[edge[u].to]-j)))*edge[u].len);
			}
		}
	}
}
int main(){
	freopen("t1.in","r",stdin);
	freopen("t1.out","w",stdout);
	splay(n),splay(k);
	for(ll i=1;i<n;i++){
		ll x,y,z;
		splay(x),splay(y),splay(z);
		addedge(x,y,z),addedge(y,x,z);
	}
	memset(dp,-63,sizeof dp);
	dfs(1,0);
	cout<<dp[1][k]<<endl;
}

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#define foreach(u,now) for(int u=first[now];u;u=edge[u].next)
#define ll long long
#define inf 1000000000
#define mod 1000000000
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
int n,m,cnt;
int last[100005];
int id,pos[100005],mx[100005],v[100005];
int bl[100005],size[100005],fa[100005];
ll tag[400005],sum[400005];
struct Edge
{
	int to,next;
}edge[200005];
void addedge(int u,int v)
{
	edge[++cnt]=(Edge){v,last[u]};last[u]=cnt;
	edge[++cnt]=(Edge){u,last[v]};last[v]=cnt;
}
void dfs(int x)
{
	size[x]=1;
	for(int i=last[x];i;i=edge[i].next)
		if(edge[i].to!=fa[x])
		{
			fa[edge[i].to]=x;
			dfs(edge[i].to);
			size[x]+=size[edge[i].to];
			mx[x]=max(mx[x],mx[edge[i].to]);
		}
}
void dfs2(int x,int cha)
{
	bl[x]=cha;pos[x]=mx[x]=++id;
	int k=0;
	for(int i=last[x];i;i=edge[i].next)
		if(edge[i].to!=fa[x]&&size[edge[i].to]>size[k])
			k=edge[i].to;
	if(k)dfs2(k,cha),mx[x]=max(mx[x],mx[k]);
	for(int i=last[x];i;i=edge[i].next)
		if(edge[i].to!=fa[x]&&edge[i].to!=k)
			dfs2(edge[i].to,edge[i].to),mx[x]=max(mx[x],mx[edge[i].to]);
}
void pushdown(int l,int r,int k)
{
	if(l==r)return;
	int mid=(l+r)>>1;ll t=tag[k];tag[k]=0;
	tag[k<<1]+=t;tag[k<<1|1]+=t;
	sum[k<<1]+=t*(mid-l+1);
	sum[k<<1|1]+=t*(r-mid);
}
void add(int k,int l,int r,int x,int y,ll val)
{
	if(tag[k])pushdown(l,r,k);
	if(l==x&&y==r){tag[k]+=val;sum[k]+=(r-l+1)*val;return;}
	int mid=(l+r)>>1;
	if(x<=mid)add(k<<1,l,mid,x,min(mid,y),val);
	if(y>=mid+1)add(k<<1|1,mid+1,r,max(mid+1,x),y,val);
	sum[k]=sum[k<<1]+sum[k<<1|1];
}
ll query(int k,int l,int r,int x,int y)
{
	if(tag[k])pushdown(l,r,k);
	if(l==x&&y==r)return sum[k];
	int mid=(l+r)>>1;
	ll ans=0;
	if(x<=mid)ans+=query(k<<1,l,mid,x,min(mid,y));
	if(y>=mid+1)ans+=query(k<<1|1,mid+1,r,max(mid+1,x),y);
	return ans;
}
ll query(int x)
{
	ll ans=0;
	while(bl[x]!=1)
	{
		ans+=query(1,1,n,pos[bl[x]],pos[x]);
		x=fa[bl[x]];
	}
	ans+=query(1,1,n,1,pos[x]);
	return ans;
}
int main()
{
	freopen("xxx.in","r",stdin);
	freopen("xxx.out","w",stdout);
	R(n),R(m);
	for(int i=1;i<=n;i++)R(v[i]);
	for(int i=1;i<n;i++)
	{
		int u,v;
		R(u),R(v);
		addedge(u,v);
	}
	dfs(1);
	dfs2(1,1);
	for(int i=1;i<=n;i++)add(1,1,n,pos[i],pos[i],v[i]);
	int opt,x,a;
	while(m--)
	{
		R(opt);R(x);
		if(opt==1)R(a),add(1,1,n,pos[x],pos[x],a);
		if(opt==2)R(a),add(1,1,n,pos[x],mx[x],a);
		if(opt==3)printf("%lld\n",query(x));
	}
	return 0;
}

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define ld long double
#define db double
#define lowbit(i) ((i)&(-(i)))
#define eps (1e-9)
ld a[1148576];
ld s[1148576];
int main(){
	freopen("set.in","r",stdin);
	freopen("set.out","w",stdout);
	int n;cin>>n;s[0]=1;
	for(int i=0;i<(1<<n);i++){
		db x;scanf("%lf",&x);a[i]=(ld)x;
	}
	int can=0;
	for(int i=0;i<(1<<n);i++){
		if(a[i]>eps)can|=i;
	}
	if(can!=(1<<n)-1)puts("INF"),exit(0);
	for(int i=1;i<(1<<n);i<<=1){
		for(int j=0;j<=(1<<n);j++){
			if(!(i&j))a[i+j]+=a[j];
		}
	}
	ld ans=0;
	for(int i=0;i<(1<<n)-1;i++){
		if(i)s[i]=-s[i-lowbit(i)];//1的个数,在第几层 
		ans+=s[i]/(1-a[i]);
	}
	if(ans<0)ans=-ans;
	printf("%0.9f",(db)ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值