考场思路:

倒着算就是

可以对一个数-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的更多相关文章

  1. 2017 清北济南考前刷题Day 7 afternoon

    期望得分:100+100+30=230 实际得分:100+100+30=230 1. 三向城 题目描述 三向城是一个巨大的城市,之所以叫这个名字,是因为城市中遍布着数不尽的三岔路口.(来自取名力为0的 ...

  2. 2017 清北济南考前刷题Day 1 afternoon

    期望得分:80+30+70=180 实际得分:10+30+70=110 T1 水题(water) Time Limit:1000ms   Memory Limit:128MB 题目描述 LYK出了道水 ...

  3. 2017 清北济南考前刷题Day 3 morning

    实际得分:100+0+0=100 T1 右上角是必败态,然后推下去 发现同行全是必胜态或全是必败态,不同行必胜必败交叉 列同行 所以n,m 只要有一个是偶数,先手必胜 #include<cstd ...

  4. 2017 清北济南考前刷题Day 3 afternoon

    期望得分:100+40+100=240 实际得分:100+40+100=240 将每个联通块的贡献乘起来就是答案 如果一个联通块的边数>点数 ,那么无解 如果边数=点数,那么贡献是 2 如果边数 ...

  5. 2017 清北济南考前刷题Day 4 afternoon

    期望得分:30+50+30=110 实际得分:40+0+0=40 并查集合并再次写炸... 模拟更相减损术的过程 更相减损术,差一定比被减数小,当被减数=减数时,停止 对于同一个减数来说,会被减 第1 ...

  6. 2017 清北济南考前刷题Day 7 morning

    期望得分:100+50+20=170 实际得分:10+50+20=80 1. 纸牌 题目描述 在桌面上放着n张纸牌,每张纸牌有两面,每面都写着一个非负整数.你的邪王真眼可以看到所有牌朝上的一面和朝下的 ...

  7. 2017 清北济南考前刷题Day 6 afternoon

    期望得分:100+100+30=230 实际得分: 正解: 枚举最高的位,这一位m是1但实际用了0 然后剩余的低位肯定是 正数就用1,负数用0 考场思路:数位DP #include<cstdio ...

  8. 2017 清北济南考前刷题Day 6 morning

    T1 贪心 10 元先找5元 20元 先找10+5,再找3张5 #include<cstdio> using namespace std; int m5,m10,m20; int main ...

  9. 2017 清北济南考前刷题Day 5 afternoon

    期望得分:100+100+30=230 实际得分:0+0+0=30 T1 直接模拟 #include<cstdio> #include<iostream> using name ...

  10. 2017 清北济南考前刷题Day 5 morning

    期望得分:100+100+0=200 实际得分: 坐标的每一位不是0就是1,所以答案就是 C(n,k) #include<cstdio> #include<iostream> ...

随机推荐

  1. 谈对“Git”的认识与理解

    自诞生于2005年以来,Git日臻完善,在高度易用的同时,仍然保留着初期设定的目标.它的速度飞快,及其适合管理大项目,它还有着令人难以置信的非线性分支管理系统,可以应付各种复杂的项目开发需求.接着说说 ...

  2. Beta后续感想/吐槽

    感想 磨人的软工实践终于结束了 艰难的度过了一学期,还是写点什么纪念一下吧. 大一大二的时候就听说软工实践是魔鬼般的锻炼,于是当年不知天高地厚的我是很期待的,终于,我大三了. 后来,我长大了. alp ...

  3. Teamwork(The fifth day of the team)

    在前面几天的努力中,我们已经完成了一些自己的工作,还有的就是一些完善,因为在前段时间一直都在寻找和配置Eclipse+Android SDK,由于版本和一些网络的阻碍,总是不能如愿的很好完成,经过了一 ...

  4. 【CSAPP笔记】11. 存储器层次结构

    在没有专门研究存储器系统之前,我们依赖的存储器模型是一个很简单的概念,也就是把它看成一个线性数组,CPU 能在一个常数时间内访问任何一个存储器位置.虽然在研究别的问题时,这是一个有效的模型,但是它不能 ...

  5. frist Django app — 一、 创建工程(转载)

    转载地址:https://www.cnblogs.com/sunshine-2015/p/5658283.html 缘起 既然python都学了,学习python的时候感觉是相见恨晚,一种新的编程语言 ...

  6. [BUAA_SE_2017]提问回顾

    提问回顾 学期初疑问回答 学期初疑问博客 教材中说,PM在衡量需求时需要方方面面的能力与研究.可是,当下许多互联网IT公司只承担外包业务,即客户给什么需求就实现什么需求,甚至可能不要求其它先进的功能. ...

  7. java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ClassLoadingException

    下载高版本的: hibernate-commons-annotations-5.0.1.Final.jar 低版本缺包

  8. C#全局钩子和局部钩子记录

    源自:https://blog.csdn.net/programvae/article/details/80292076 最近碰巧要使用键盘钩子,于是在网上搜索了一番,发现大多数博客的文章都是雷同的, ...

  9. NOI前训练日记

    向别人学习一波,记点流水帐.17.5.29开坑. 5.29 早晨看了道据说是树状数组优化DP的题(hdu5542),然后脑补了一个复杂度500^3的meet in the middle.然后死T... ...

  10. P2144 [FJOI2007]轮状病毒

    题目描述 轮状病毒有很多变种.许多轮状病毒都是由一个轮状基产生.一个n轮状基由圆环上n个不同的基原子和圆心的一个核原子构成.2个原子之间的边表示这2个原子之间的信息通道,如图1. n轮状病毒的产生规律 ...