test 11-10 [水题 状压DP dfs序+线段树]
来源:互联网 发布:淘宝虚拟网店取消 编辑:程序博客网 时间:2024/06/04 18:01
第一题水题,略过。。。
T2
【题目描述】
我们要从n种食物选m个出来,安排一个顺序吃掉它(们),每种食物有个美味值ai,然后我们有k个规则,每个规则有 xi, yi 和 ci三个数,如果吃完第xi种食物接下来马上吃第yi种食物,第j种食物的美味值会增加ci。每种食物至多吃一个,求美味值最大的和是多少?
【输入格式】
第一行有三个数n,m,k,k代表有k个规则(0<=k<=n*(n-1))。第二行有n个数字代表每个食物的美味值。接下去有k行,每行三个数xi,yi,ci。保证没有任意两个规则的xi和yi同时相同。
【输出格式】
一行一个数代表答案
【sample input1】
2 2 11 12 1 1
【sample output1】
3
【sample input 2】
4 3 21 2 3 42 1 53 4 2
【sample output 2】
12
【数据范围】
30% m<=n<=5 ,0<=ci,ai<=1e5100% m<=n<=18,0<=ci,ai<=1e9
状压dp,用记忆化搜索比较简便,主要是再加一个状态,表示上一次取的,即可得转移方程:
dp(S,i,j)=max{dp(S’,k,j-1)}
其中,j,这个状态是指取了多少个,但是S已经表示了,记忆化的时候不用加这一维,这里只是为了方便。
代码样本:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define maxn 25#define maxbit 300000typedef long long ll;ll f[maxbit][maxn],w[maxn],ad[maxn][maxn];int p[maxn],n,m,k;bool vis[maxbit][maxn];ll dp(int s,int las,int nu){ if(nu==m)return 0; if(vis[s][las])return f[s][las]; ll &ans=f[s][las]; for(int i=1;i<=n;i++) { if(s&p[i])continue; if(ad[las][i]) ans=(ll)max(ans,dp(s|p[i],i,nu+1)+ad[las][i]+w[i]); else ans=(ll)max(ans,dp(s|p[i],i,nu+1)+w[i]); } vis[s][las]=true; return ans;}int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) { scanf("%I64d",&w[i]); p[i]=1<<(i-1); } int a,b; ll val; while(k--) { scanf("%d%d%I64d",&a,&b,&val); ad[a][b]=val; } printf("%I64d",dp(0,0,0)); return 0;}
T3
【题目描述】
历史上有一个著名的王国。它的所有城市互相连通并且构成一棵树。城市1为首都也就是这棵树的根。 因为外来的入侵,国王决定在某些城市加派士兵。所有城市初始士兵数量为0。当城市i 被加派了k 名士兵时。城市i 的所有子城市需要被加派k+1 名士兵。这些子城市的所有子城市需要被加派k+2 名士兵。以此类推。 当然,加派士兵的同时,国王也需要不断了解当前的情况。于是他随时可能询问以城市i 为根的子树中的所有城市共被加派了多少士兵。 你现在是国王的军事大臣,你能回答出国王的每个询问么?
【输入】
第一行,包含两个整数N,P 代表城市数量以及国王的命令的数量。 接下来的P 行,每行代表国王的一个命令,命令分两种 A X K :在城市X 加入K 个士兵 Q X :询问以城市X 为根的子树中所有士兵数量的和
【输出】
对于每个Q,输出答案。
【输入样例】
7 10 1 1 2 2 5 5 Q 1 A 2 1 Q 1 Q 2 Q 5 A 5 0 Q 5 A 3 1 Q 1 Q 2
【输出样例】
0 11 11 8 10 14 13
【数据范围】
对于50%的数据, 1<=N<=1000 1<=P<=300 对于100%的数据, 1<=N<=50000 1<=P<=100000 1<=X<=N 0<=K<=1000
经过推导,可得:
然后把点用dfs序存下
最后线段树,区间修改,区间查找
即:最终的值等于k减去该点深度,乘以子树大小加上子树深度和。
记住要记录add和tim(加的次数)的值,而且add可能为0,因此判断pushdown的标准是tim不为0而不是add
代码样本:
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<set>#include<algorithm>using namespace std;#define L(u) (u<<1)#define R(u) ((u<<1)|1)#define maxn 50005struct tre{ int l,r;}nod[maxn*4];typedef long long ll;ll d[maxn],ma[maxn],sum[maxn*4],ad[maxn*4],sd[maxn],ti[maxn*4],k;int head[maxn],tov[maxn],next[maxn],n,p,a,size[maxn],dfn[maxn],num;int dfs(int u){ size[u]=1; dfn[u]=++num; ma[num]=u; int v=head[u]; while(v) { d[tov[v]]=d[u]+1; size[u]+=dfs(tov[v]); v=next[v]; } return size[u];}void build(int u,int le,int ri){ nod[u].l=le,nod[u].r=ri; if(le==ri) { return ; } int mid=(le+ri)/2; build(L(u),le,mid); build(R(u),mid+1,ri);}ll upg(ll val,int po){ return val-d[po];}void pushdown(int u){ sum[L(u)]+=(nod[L(u)].r-nod[L(u)].l+1)*ad[u]+(sd[nod[L(u)].r]-sd[nod[L(u)].l-1])*ti[u]; sum[R(u)]+=(nod[R(u)].r-nod[R(u)].l+1)*ad[u]+(sd[nod[R(u)].r]-sd[nod[R(u)].l-1])*ti[u]; ad[L(u)]+=ad[u]; ad[R(u)]+=ad[u]; ti[L(u)]+=ti[u]; ti[R(u)]+=ti[u]; ad[u]=0; ti[u]=0;}void update(int u,int le,int ri,ll val,int po){ if(nod[u].l>=le&&nod[u].r<=ri) { sum[u]+=(nod[u].r-nod[u].l+1)*upg(val,po)+sd[nod[u].r]-sd[nod[u].l-1]; ad[u]+=upg(val,po); ti[u]++; return; } if(ad[u]||ti[u]) pushdown(u); int mid=(nod[u].l+nod[u].r)/2; if(ri<=mid)update(L(u),le,ri,val,po); else if(le>mid)update(R(u),le,ri,val,po); else { update(L(u),le,mid,val,po); update(R(u),mid+1,ri,val,po); } sum[u]=sum[L(u)]+sum[R(u)];}ll query(int u,int le,int ri){ if(nod[u].l==le&&nod[u].r==ri) { return sum[u]; } if(ad[u]||ti[u])pushdown(u); int mid=(nod[u].l+nod[u].r)/2; if(ri<=mid)return query(L(u),le,ri); else if(le>mid) return query(R(u),le,ri); else return query(L(u),le,mid)+query(R(u),mid+1,ri);}int main(){ freopen("c.in","r",stdin); freopen("c.out","w",stdout); scanf("%d%d",&n,&p); for(int i=2;i<=n;i++) { scanf("%d",&a); tov[i]=i; next[i]=head[a]; head[a]=i; } d[1]=1; dfs(1); for(int i=1;i<=n;i++) sd[i]=sd[i-1]+d[ma[i]]; build(1,1,n); char op; while(p--) { scanf(" %c ",&op); if(op=='A') { scanf("%d%I64d",&a,&k); update(1,dfn[a],dfn[a]+size[a]-1,k,a); } else { scanf("%d",&a); printf("%I64d\n",query(1,dfn[a],dfn[a]+size[a]-1)); } } return 0;}
0 0
- test 11-10 [水题 状压DP dfs序+线段树]
- [NOIP模拟题][杂题][状压DP][DFS序][线段树]
- NOIP模拟题 2016.11.10 [模拟] [状压DP] [线段树] [DFS序]
- [NOIP模拟][状压dp][dfs序列][线段树]
- Paths 升级(DFS序+线段树+LCA+树形DP)
- (线段树+dfs序)
- DFS序+线段树
- test 11-14 [dp 倍增 前缀和 线段树 离散化]
- HDU5692 线段树+dfs序
- 【线段树+dfs序】J
- 线段树2.0+dfs序
- 2012 ACM/ICPC Asia Regional Changchun Online(hdu 4267 - 4277)线段树+dp+dfs+树形dp
- 【bzoj3306】 树 dfs序+线段树
- 【bzoj3306】【树】【dfs序+线段树】
- bzoj 3306: 树 dfs序+线段树
- [bzoj3306]树 dfs序+线段树
- Codeforces 384E 线段树+dfs序
- hdu 5039 Hilarity(dfs序 + 线段树)
- JavaScript也能写爬虫-新浪微博【按关键字】采集爬虫
- TextView显示单行文本多余...显示
- jsp 取得DataGrid数据的代码实例(有checkBoxs 的DataGrid)
- orcle序列的创建删除
- Notepad++的列编辑功能
- test 11-10 [水题 状压DP dfs序+线段树]
- RotateAnimation 动画的参数详解
- android 下c++创建文件摘要
- JavaScript的showModalDialog
- codevs 1200 同余方程(扩展欧几里德)
- xxxActivity did not call through to super.onStart()等方法SuperNotCalledException的源码分析
- nginx的timer delta:日志
- MySQL用变量的方法添加伪序号列,MySql自增序列,序号列
- 解压缩读取Dicom图片(彩色)及显示