【62测试】【状压dp】【dfs序】【线段树】
第一题:
给出一个长度不超过100只包含'B'和'R'的字符串,将其无限重复下去。
比如,BBRB则会形成
BBRBBBRBBBRB
现在给出一个区间[l,r]询问该区间内有多少个字符'B'(区间下标从1开始) [1<=l,r<=1e18]
解: 没想到第一题这么水。直接前缀和+mod就可以了,再判一下边界。注意1e18不需要高精度。long long 有9*10^18.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 105
#define ll long long
using namespace std;
char c[maxn];
ll len,ans,l,r,sum[maxn];
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%s",c+);
cin>>l>>r;
len=strlen(c+);
for (int i=;i<=len;i++)
{
sum[i]=sum[i-];
if (c[i]=='B') sum[i]++;
}
ans=(r/len)*sum[len]+sum[r%len]-(l/len)*sum[len]-sum[l%len];
if ((l%len==&&c[len]=='B')||c[l%len]=='B') ans++;
printf("%I64d",ans);
return ;
}
第二题:(codeforces 580D:Kefa and Dishes)
我们要从n种食物选m个出来,安排一个顺序吃掉它(们),每种食物有个美味值ai,然后我们有k个规则,每个规则有 xi, yi 和 ci三个数,如果吃完第xi种食物接下来马上吃第yi种食物,第j种食物的美味值会增加ci。每种食物至多吃一个,求美味值最大的和是多少?
n,m<=18,ai,ci<=10^9
解:
看到这么小的数据范围就是状压dp了。想到是第一次自己写,还是很欣慰的得了50%。我的方法是f[i][j]表示选了 i 个的状态 j 。写转移方程的时候遇到了问题,不能表示上一个选的是什么(而从这一点出发可以想到换第一维的表示,可以换为last取的食物,于是我与标答失之交臂)所以把 f 写了一个结构体,存下美味值和上一次选的食物。然后就是转移方程,我先循环m,然后枚举所有状态,判断该状态是否符合只取了当前个食物,然后枚举n,加入下一个状态。
还是不知道为什么WA了5个点,等写完博客来看看。
50分代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 300000
#define maxn 20
#define ll long long
using namespace std;
int n,m,k,ma;
ll v[maxn];
struct pp{
ll tastyy;
int chos;
};
pp f[maxn][M];
ll ad[maxn][maxn];
bool pd(int x,int y)
{
int sum=;
for (int i=;i<n;i++)
{
if ((<<i)&x) sum++;
if (sum>y-) return false;
}
if (sum==y-) return true;
else return false;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<=n;i++)
scanf("%I64d",&v[i]);
for (int i=;i<=k;i++)
{
int x,y;
ll z;
scanf("%d%d%I64d",&x,&y,&z);
ad[x][y]=z;
}
for (int i=;i<=m;i++)
{
f[i][].tastyy=-;
ma=(ma|(<<(n-i)));//n-i
}
for (int i=;i<=n;i++)
{
int x=(<<(i-));// not f[1][i]
f[][x].tastyy=v[i];
f[][x].chos=i;
}
for (int i=;i<=m;i++)
{
for (int j=;j<=ma;j++)
if (pd(j,i)&&f[i-][j].tastyy){
for (int k=;k<=n;k++)
if (f[i][(j&(<<(k-)))].tastyy==-){
int cur=(j|(<<(k-)));//k-1
ll add=;
if (ad[f[i-][j].chos][k]) add=ad[f[i-][j].chos][k];
if (f[i-][j].tastyy+v[k]+add>=f[i][cur].tastyy){//放在括号内
f[i][cur].tastyy=f[i-][j].tastyy+v[k]+add;
f[i][cur].chos=k;
}
}
}
}
ll ans=;
for (int i=;i<=ma;i++)
if (f[m][i].tastyy>=){
if (f[m][i].tastyy>=ans) ans=f[m][i].tastyy;
}
printf("%I64d",ans);
return ;
}
说说正解。这道题当初电子科大那位讲过,我说怎么这么眼熟。用f[i][j]表示最后一个选 j 的状态 i 。第一层枚举所有状态,进入后判断是否选了m个更新答案,否则,第二层循环当前要选的点,如果当前状态没有选过,那么进入第三层,循环上一次能选的点,更新状态:f[(i|(1<<(j-1)))][j]=max(f[(i|(1<<(j-1)))][j],f[i][k]+ad[k][j]+v[j]) 。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 300000
#define maxn 20
#define ll long long
using namespace std;
int n,m,k;
ll v[maxn],f[M][maxn],ad[maxn][maxn],ans;
bool pd(int x)
{
int sum=;//sum=0
for (int i=;i<=n;i++)
if ((<<(i-))&x) sum++;//&x
if (sum==m) return true;
else return false;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
cin>>n>>m>>k;
for (int i=;i<=n;i++)
scanf("%I64d",&v[i]);
for (int i=;i<=k;i++)
{
int x,y;
ll z;
scanf("%d%d%I64d",&x,&y,&z);
ad[x][y]=z;
}
for (int i=;i<n;i++)
f[(<<i)][i+]=v[i+];
int idx=;
for (int i=;i<=(<<n);i++)
{
if (pd(i)){
for (int j=;j<=n;j++)
if (f[i][j]>ans) ans=f[i][j];
}
else{
for (int j=;j<=n;j++)
{
if (((i>>(j-))&)==)
{//没有吃
for (int k=;k<=n;k++)
if ((i>>(k-))&)//枚举吃过的最后一个
{
if (f[i][k]+ad[k][j]+v[j]>f[(i|(<<(j-)))][j])
f[(i|(<<(j-)))][j]=f[i][k]+ad[k][j]+v[j];
}
}
}
}
}
printf("%I64d",ans);
return ;
}
第三题:
因为外来的入侵,国王决定在某些城市加派士兵。所有城市初始士兵数量为0。当城市i被加派了k名士兵时。城市?的所有子城市需要被加派k + 1名士兵。这些子城市的所有子城市需要被加派k +2名士兵。以此类推。当然,加派士兵的同时,国王也需要不断了解当前的情况。于是他随时可能询问以城市 i 为根的子树中的所有城市共被加派了多少士兵。你现在是国王的军事大臣,你能回答出国王的每个询问么?
输入格式
第一行,包含两个整数N,P代表城市数量以及国王的命令的数量。
第二行N −1个整数,表示2− N号每个节点的父亲节点。
接下来的P行,每行代表国王的一个命令,命令分两种:
A X K在城市X加入K个士兵
Q X 询问以城市X为根的子树中所有士兵数量的和。
n<=50000,p<=100000
解: 考试时用20多分钟打的暴力,过了50%。然后这套题就考了200。这是集训以来考的最好的一次,第4吧。
说正事。这道题的正解:dfs序+线段树。
dfs序:按照dfs的搜索顺序,一个节点的所有子树都是连续的标号,所以对于这个节点有一个最大区间,可以用线段树进行维护。(QAQ树套树-_-)
最终还是逃不过线段树。每一次操作u节点对于u的某一子树上的节点v而言,需要加上的值为k+dep[v]-dp[u]. dep[v]为节点本身的性质,而k-dep[u]为子树的性质。所以可以把它分为两部分处理。一个节点如果被操作了tot次,那么第一部分为tot*dep[v] , 对于子树而言,为tot*∑dep[v]。同样第二部分,每个子节点都是k-dep[u],所以对于这棵子树为size*(k-dep[u]).
然后就是线段树的长长代码.....还要多练啊。提速。注意一些细节,毕竟代码长了容易犯小错误,而且这样的小错是很难找到的。我运气还算比较好。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50005
#define ll long long
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
int n,q,ans,idx;
int tot,ne[maxn*],to[maxn*],he[maxn],id[maxn];
int xul[maxn],xur[maxn],depth[maxn]; void add(int a,int b)
{
tot++;to[tot]=b;ne[tot]=he[a];he[a]=tot;
}
void dfs_xu(int x,int fa,int dep)
{
depth[x]=dep;
xul[x]=++idx;//正序左
id[idx]=x;//反之
for (int i=he[x];i;i=ne[i])
if (to[i]!=fa){
dfs_xu(to[i],x,dep+);
}
xur[x]=idx;//右端点
}
/* /*-----------------xian_duan_shu-----------------------*/
struct pp{
ll dep,sum_tot,tot;//sum_tot: part_1
ll cha,sum_cha,size;//sum_cha作为子树的sum,cha 作为单点的cha,
};
pp tree[maxn*];
/*-------------add_dan----------------*/
void add_tot(int x,ll val)
{
tree[x].tot+=val;
tree[x].sum_tot+=val*tree[x].dep;
}
void add_cha(int x,ll val)
{
tree[x].cha+=val;
tree[x].sum_cha+=val*tree[x].size;
}
/*-------------------pushdown--------------------*/
void pushdown_tot(int cur)
{
if (!tree[cur].tot) return ;
add_tot(L(cur),tree[cur].tot);
add_tot(R(cur),tree[cur].tot);
tree[cur].tot=;
}
void pushdown_cha(int cur)
{
if(!tree[cur].cha) return ;
add_cha(L(cur),tree[cur].cha);
add_cha(R(cur),tree[cur].cha);
tree[cur].cha=;
}
/*----------------------uptate_sum---------------------*/
void uptate_tot(int cur)
{
tree[cur].sum_tot=tree[L(cur)].sum_tot+tree[R(cur)].sum_tot;
}
void uptate_cha(int cur)
{
tree[cur].sum_cha=tree[L(cur)].sum_cha+tree[R(cur)].sum_cha;
}
/*-----------------------------opreate-------------------------------*/
void change_tot(int cur,int l,int r,int x,int y,ll val)
{
if (l>=x&&r<=y)
{
add_tot(cur,val);
return ;
}
pushdown_tot(cur);
int mid=(l+r)>>;
if (x<=mid&&l<=y) change_tot(L(cur),l,mid,x,y,val);
if (y>=mid+&&x<=r) change_tot(R(cur),mid+,r,x,y,val);
uptate_tot(cur);
}
void change_cha(int cur,int l,int r,int x,int y,ll val)
{
if (l>=x&&r<=y)
{
add_cha(cur,val);
return ;
}
pushdown_cha(cur);
int mid=(l+r)>>;
if (x<=mid&&l<=y) change_cha(L(cur),l,mid,x,y,val);
if (y>=mid+&&x<=r) change_cha(R(cur),mid+,r,x,y,val);
uptate_cha(cur);
}
ll query(int cur,int l,int r,int x,int y)
{
if (x<=l&&r<=y)
return tree[cur].sum_tot+tree[cur].sum_cha;
pushdown_tot(cur);pushdown_cha(cur);
int mid=(l+r)>>;
ll an=;
if (x<=mid&&l<=y) an+=query(L(cur),l,mid,x,y);
if (y>=mid+&&x<=r) an+=query(R(cur),mid+,r,x,y);
return an;
}
/*----------------------build-----------------------*/ void update_build(int u)
{
tree[u].size=tree[L(u)].size+tree[R(u)].size;
tree[u].dep=tree[L(u)].dep+tree[R(u)].dep;//细节
}
void build(int l,int r,int u)
{
if (l==r)
{
tree[u].dep=depth[id[l]];
tree[u].size=;
return ;//****
}
int mid=(l+r)>>;
build(l,mid,L(u));
build(mid+,r,R(u));//mid+1
update_build(u);
}
/*-------------------------main----------------------------*/
int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
cin>>n>>q;
for (int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
add(x,i);
add(i,x);
}
dfs_xu(,,);
build(,n,);
while (q)
{
char c[];int x;
scanf("%s",c);
if (c[]=='A') {
int x;
ll y;
scanf("%d"AUTO,&x,&y);
change_tot(,,n,xul[x],xur[x],);
change_cha(,,n,xul[x],xur[x],y-depth[x]);
}
else {
int x;
scanf("%d",&x);
ll ans=query(,,n,xul[x],xur[x]);
printf(AUTO,ans);
printf("\n");
}
q--;
}
return ;
}
【62测试】【状压dp】【dfs序】【线段树】的更多相关文章
- BZOJ 3252题解(贪心+dfs序+线段树)
题面 传送门 分析 此题做法很多,树形DP,DFS序+线段树,树链剖分都可以做 这里给出DFS序+线段树的代码 我们用线段树维护到根节点路径上节点权值之和的最大值,以及取到最大值的节点编号x 每次从根 ...
- Codeforces Round #442 (Div. 2)A,B,C,D,E(STL,dp,贪心,bfs,dfs序+线段树)
A. Alex and broken contest time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- HDU 4272 LianLianKan (状压DP+DFS)题解
思路: 用状压DP+DFS遍历查找是否可行.假设一个数为x,那么他最远可以消去的点为x+9,因为x+1~x+4都能被他前面的点消去,所以我们将2进制的范围设为2^10,用0表示已经消去,1表示没有消去 ...
- bjtu 1846. Infinity的装备[状压dp+dfs/bfs]
https://citel.bjtu.edu.cn/acm/oj/problem/1846 1846. Infinity的装备 时间限制 1000 ms 内存限制 64 MB 题目描述 “测试服终于下 ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- POJ 3321 DFS序+线段树
单点修改树中某个节点,查询子树的性质.DFS序 子树序列一定在父节点的DFS序列之内,所以可以用线段树维护. 1: /* 2: DFS序 +线段树 3: */ 4: 5: #include < ...
- CodeForces 877E DFS序+线段树
CodeForces 877E DFS序+线段树 题意 就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身 ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
随机推荐
- opencv的学习笔记3
CMake是一个比make更高级的编译配置工具,它可以根据不同平台.不同的编译器,生成相应的Makefile或者vcproj项目.通过编写CMakeLists.txt,可以控制生成的Makefile, ...
- 关于qt的集成开发环境
事情是这样的,在archlinux中安装好qt5之后,只发现了一个 qt designer,这个只能用来写界面.其它的几个程序(qt assistant)算是查文档的这类辅助的程序. 记得在windo ...
- servlet1
1.jsp其实就是servlet 2.一个java类实现servlet接口,然后在浏览器端访问即可
- AppCan接入微信并且进行文字分享
AppCan接入微信并且进行文字分享 接入指引 实现简单的文字分享功能 接入指引 详情请参见:http://newdocx.appcan.cn/index.html?templateId=412 实现 ...
- MSDTC故障排除
“由于 Microsoft 分布式事务处理协调器出现问题,因此无法连接到配置数据库. 该事务管理器已经禁止了它对远程/网络事务的支持". 第一步: 请确保iis(运行程序的机器)和sql ...
- Java 菜鸟学习之 script脚本语句
脚本语句 一般分为 顺序语句 分支语句 循环语句 顺序语句 就是从上到下依次读取 分支语句 是if语句 if(判断条件) { 满足条件执行的语句 } else { 不满足条件执行的语句 ...
- 在li元素中放入img图片时li的高度问题
在li元素中放入img图片时li的高度会比img图片的高度多出几个像素,解决这个问题只需要将img元素的css设置成vertical-align: middle;就可以解决.
- Going from u to v or from v to u?_POJ2762强连通+并查集缩点+拓扑排序
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Description I ...
- /var/spool/postfix/maildrop 占用inode索引及磁盘空间解决办法
1.问题表现和检查 运行df -i / 查看inode使用是否满: 2.查看/var/spool/postfix/maildrop是否有非常多的小文件,ls直接卡死等情况 解决: 删除小文件: cd ...
- EntityFramework Core 学习笔记 —— 包含与排除类型
原文地址:https://docs.efproject.net/en/latest/modeling/included-types.html 在模型类中包含一种类型意味着 EF 拥有了这种类型的元数据 ...