2017 清北济南考前刷题Day 4 morning
考场思路:
倒着算就是
可以对一个数-1
可以合并两个数
可以证明只有0和0才能执行合并操作
然后模拟
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 1000001 void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} int a[N]; int main()
{
//freopen("multiset.in","r",stdin);
// freopen("multiset.out","w",stdout);
int n;
read(n);
int sum0=,cnt=,x;
for(int i=;i<=n;i++)
{
read(x);
if(!x) sum0++;
else a[++cnt]=x;
}
sort(a+,a+cnt+);
long long ans=,gather=;
for(int i=;i<=cnt;i++)
{
if(!a[i]) break;
a[i]-=gather;
x=a[i]; gather+=x; ans+=x;
while(x)
{
x--;
if(sum0>) sum0=sum0+>>;
else break;
}
sum0++;
while(i<cnt && a[i+]-gather==)
{
sum0++;
a[++i]-=gather;
}
}
while(sum0>) ans++,sum0=sum0+>>;
cout<<ans;
}
考场上没注意有向图。。。。
一条道路如果能在上一组,那么肯定把它放在上一组最优
所以可以没加一条边,就判断当前1和n是否联通
判断方式: u-->v若现在u没有与1联通,就不管他
若u和v都与1联通了,那也不管他
若 u与1联通,而v 没有联通,那就再从v开始bfs
这样 每条边只会被访问一次
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream> using namespace std; #define N 200001
#define M 500001 int n; int front[N],nxt[M],to[M],tot; bool vis[N]; int use[N],cnt; queue<int>q; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
} bool bfs(int s)
{
if(s==n) return true;
while(!q.empty()) q.pop();
q.push(s);
int now;
while(!q.empty())
{
now=q.front(); q.pop();
for(int i=front[now];i;i=nxt[i])
if(!vis[to[i]])
{
use[++cnt]=to[i];
if(to[i]==n) return true;
vis[to[i]]=true;
q.push(to[i]);
}
}
return false;
} int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
int m;
read(n); read(m);
int u,v; int ans=;
vis[]=true;
for(int i=;i<=m;++i)
{
read(u); read(v);
if(vis[u] && !vis[v])
{
add(u,v);
vis[v]=true;
use[++cnt]=v;
if(bfs(v))
{
// printf("%d\n",i);
for(int i=;i<=cnt;++i) vis[use[i]]=false,front[use[i]]=;
front[]=;
cnt=tot=; ans++;
add(u,v);
if(u!=) use[++cnt]=u;
if(u==) vis[v]=true,use[++cnt]=v;
}
}
else if(!(vis[u] && vis[v])) add(u,v),use[++cnt]=u;
}
cout<<ans;
}
std思路:
结合了倍增的二分
如果用朴素的二分,会被m条边分m组卡成mm
先考虑1条边 能否使其联通,不能再考虑2条边,然后4条,8条……
若在2^p时 不能联通了,那么在2^p-1 ~ 2^p 范围内二分
这样时间复杂度是mlogm的
如果小兵的血量是1 2 3 4 5 ……
那么显然我们可以补到所有的兵
如果有相同血量的兵,那么只能补到其中的1个兵
所以我们要尽可能的把给出的兵的血量变成1 2 3 4 5 ……
一种可行的方案是 重复血量的兵 强制消耗代价使他 变成 血量更小 但血量不重复的兵
可以用栈记录之前没有的血量,每遇到一个重复的就用栈中的一个血量
例:1 2 4 4
扫到4的时候,之前没有血量3,3入栈
后面还是1个4,就让3出栈,即消耗代价 使4变成3
令c[i]=j 记录消耗代价后血量为i的兵实际上是原血量为j的兵
然后DP
dp[i][j] 表示到血量为i的兵,省下了j刀的最大补兵数
省下了j刀:就是先把兵的血量看成1,2,3,然后考虑每个兵砍或不砍。如果不砍,就可以省下一刀给以后用
所以如果不砍,状态转移为 dp[i][j]=dp[i-1][j-1]
如果砍的话,砍血量为i的兵要加上之前强制消耗的代价,所以dp[i][j]=dp[i-1][j+c[i]-i]+1
老鹿的攻击怎么体现的呢?
因为每次尽可能的让兵的血量变为1,2,3……
自己砍掉一个血量为1的兵,后面再老鹿的攻击下又产生了一个血量为1的兵
但实际DP时
从1开始枚举血量
血量为2时,实际血量为1,相当于 提高了 兵死亡时的血量
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream> using namespace std; #define N 1001 int f[N][N]; int a[N],c[N]; int cnt[N]; int st[N],top; int main()
{
freopen("cs.in","r",stdin);
freopen("cs.out","w",stdout);
int T,n,mx;
scanf("%d",&T);
while(T--)
{
memset(f,,sizeof(f));
memset(cnt,,sizeof(cnt));
memset(c,,sizeof(c));
top=mx=;
scanf("%d",&n);
for(int i=;i<=n;++i) scanf("%d",&a[i]),mx=max(mx,a[i]),cnt[a[i]]++;
sort(a+,a+n+);
for(int i=;i<=mx;i++)
if(!cnt[i]) st[++top]=i;
else
{
while(cnt[i]> && top ) c[st[top--]]=i,--cnt[i];
c[i]=i;
}
int ans=;
for(int i=;i<=mx;++i)
for(int j=;j<i;++j)
{
if(j) f[i][j]=f[i-][j-];
if(c[i] && j+c[i]-i<i) f[i][j]=max(f[i][j],f[i-][j+c[i]-i]+);
ans=max(ans,f[i][j]);
}
cout<<ans<<'\n';
}
}
2017 清北济南考前刷题Day 4 morning的更多相关文章
- 2017 清北济南考前刷题Day 7 afternoon
期望得分:100+100+30=230 实际得分:100+100+30=230 1. 三向城 题目描述 三向城是一个巨大的城市,之所以叫这个名字,是因为城市中遍布着数不尽的三岔路口.(来自取名力为0的 ...
- 2017 清北济南考前刷题Day 1 afternoon
期望得分:80+30+70=180 实际得分:10+30+70=110 T1 水题(water) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK出了道水 ...
- 2017 清北济南考前刷题Day 3 morning
实际得分:100+0+0=100 T1 右上角是必败态,然后推下去 发现同行全是必胜态或全是必败态,不同行必胜必败交叉 列同行 所以n,m 只要有一个是偶数,先手必胜 #include<cstd ...
- 2017 清北济南考前刷题Day 3 afternoon
期望得分:100+40+100=240 实际得分:100+40+100=240 将每个联通块的贡献乘起来就是答案 如果一个联通块的边数>点数 ,那么无解 如果边数=点数,那么贡献是 2 如果边数 ...
- 2017 清北济南考前刷题Day 4 afternoon
期望得分:30+50+30=110 实际得分:40+0+0=40 并查集合并再次写炸... 模拟更相减损术的过程 更相减损术,差一定比被减数小,当被减数=减数时,停止 对于同一个减数来说,会被减 第1 ...
- 2017 清北济南考前刷题Day 7 morning
期望得分:100+50+20=170 实际得分:10+50+20=80 1. 纸牌 题目描述 在桌面上放着n张纸牌,每张纸牌有两面,每面都写着一个非负整数.你的邪王真眼可以看到所有牌朝上的一面和朝下的 ...
- 2017 清北济南考前刷题Day 6 afternoon
期望得分:100+100+30=230 实际得分: 正解: 枚举最高的位,这一位m是1但实际用了0 然后剩余的低位肯定是 正数就用1,负数用0 考场思路:数位DP #include<cstdio ...
- 2017 清北济南考前刷题Day 6 morning
T1 贪心 10 元先找5元 20元 先找10+5,再找3张5 #include<cstdio> using namespace std; int m5,m10,m20; int main ...
- 2017 清北济南考前刷题Day 5 afternoon
期望得分:100+100+30=230 实际得分:0+0+0=30 T1 直接模拟 #include<cstdio> #include<iostream> using name ...
- 2017 清北济南考前刷题Day 5 morning
期望得分:100+100+0=200 实际得分: 坐标的每一位不是0就是1,所以答案就是 C(n,k) #include<cstdio> #include<iostream> ...
随机推荐
- 2018软工实践—Alpha冲刺(10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 测试整体软件 展示GitHub当 ...
- beat冲刺(4/7)
目录 摘要 团队部分 个人部分 摘要 队名:小白吃 组长博客:hjj 作业博客:beta冲刺(4/7) 团队部分 后敬甲(组长) 过去两天完成了哪些任务 整理博客 ppt模板 接下来的计划 做好机动. ...
- 如何在mvc项目中使用apiController
文章地址:How do you route from an MVC project to an MVC ApiController in another project? 文章地址:How to Us ...
- Week2:阅读笔记与思考
<构建之法>这本书的内容通俗易懂,每一个知识点都有许多事例佐证,阅读起来不像其他教科书那样枯燥无聊.但阅读过第一.二.十六章之后还是产生了几个疑问,以及更深层次的思考. 第一章 问题1: ...
- 代码上传不到github远程仓库的经历和总结
第二次的作业是分布式版本控制系统Git的安装与使用.一切都好端端地进行,知道最后的上传到给远程仓库时一直都上传失败.舍友也过来调试和助教的指导,依然不成功.我也上网进行了大量的翻查资料也未能成功.这是 ...
- Source Insight中的多行注释
转自:http://www.cnblogs.com/dongzhiquan/archive/2013/03/04/2943448.html 我们经常要对一整段代码进行注释,很多代码编辑器都提供了这样的 ...
- <构建之法>前三章读后感—软件工程
本教材不同于其他教材一贯的理知识直接灌溉,而是以对话形式向我们传授知识的,以使我们更好地理解知识点,更加清晰明确. 第一章 第一章的概述中,书本以多种方式,形象生动地向我们阐述了软件工程的内容,也让我 ...
- PAT 甲级 1112 Stucked Keyboard
https://pintia.cn/problem-sets/994805342720868352/problems/994805357933608960 On a broken keyboard, ...
- windows多线程(一) 创建线程 CreateThread
一 线程创建函数 CreateThread 修改说明: 这里 说了另一种创建线程方法,使用_beginthreadex()更安全的创建线程,在实际使用中尽量使用_beginthreadex()来创建线 ...
- java 一般类属性设置常量 用以长久使用
java 一般类属性设置常量 用以长久使用 一直引用 例如 文件名