CONTEST36 小Z的模拟赛(2)
A.小Z的可恶路障
题目:http://www.luogu.org/problem/show?pid=U126
题解:暴力也可以过吧。我为了保险先求了一次最短路,然后枚举这条最短路上的所有边。。。
代码:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxm 100000
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
struct edge{int go,next,w,from;}e[*maxm];
int n,m,tot=,q[maxm],d[maxm],head[maxm],pre[maxm];
bool v[maxm],can[maxm];
void ins(int x,int y,int z)
{
e[++tot].go=y;e[tot].from=x;e[tot].w=z;e[tot].next=head[x];head[x]=tot;
}
void insert(int x,int y,int z)
{
ins(x,y,z);ins(y,x,z);
}
void spfa()
{
for(int i=;i<=n;++i) d[i]=inf;
memset(v,,sizeof(v));
int l=,r=,x,y;q[]=;d[]=;
while(l!=r)
{
x=q[++l];if(l==maxm-)l=;v[x]=;
for(int i=head[x];i;i=e[i].next)
if(d[x]+e[i].w<d[y=e[i].go])
{
d[y]=d[x]+e[i].w;
pre[y]=i;
if(!v[y]){v[y]=;q[++r]=y;if(r==maxm-)r=;}
}
}
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();m=read();int x,y,z;
for1(i,m)x=read(),y=read(),z=read(),insert(x,y,z);
spfa();
for(int i=pre[n];i;i=pre[e[i].from])can[i]=;
int ans=,tmp=d[n];
for1(i,tot)
if(can[i])
{
e[i].w<<=;
e[i^].w<<=;
spfa();
ans=max(ans,d[n]-tmp);
e[i].w>>=;
e[i^].w>>=;
}
printf("%d\n",ans);
return ;
}
B.小Z的游戏分队
题目:http://www.luogu.org/problem/show?pid=U127
题解:这题我做的比较满意,说一下我的做法:
首先i 不愿意与 j 在一组,那么我们就merge(i,j+n) merge(j+n,i) (做过食物链、关押罪犯的都知道什么意思吧。。。)
然后执行完之后整个图就分为了好多个块块,有些块之间有边相连,代表这两块一定不能在同一组里。
当然一个块最多只会和一个块相连,否则这两个块一定已经被缩成了一个块
然后怎么做呢?类似与搭建双塔,我们可以用一个二维可行性背包DP,当然应为总人数是确定的,所以可以缩成1维
状态如何转移呢?
f[]=;
for1(i,n)
if(s[i])
{
if(can[i])
{
for3(j,n-s[i],)
if(f[j])f[j+s[i]]=;
}
else if(b[i])
{
for3(j,n,)
if(f[j])
{
f[j]=;
if(j+s[i]<=n)f[j+s[i]]=;
if(j+s[b[i]]<=n)f[j+s[b[i]]]=;
}
}
}
应该很清楚了吧。如果 i 块没有边与其他块相连,那么它可以选择加进 a 组,或者不加进 a 组
否则 它与它相连的块要么一个在 a 组,要么 另一个在 a 组。
最后统计一下就ok了。
代码:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 100000
#define maxm 500+100
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
int n,fa[maxn],a[maxn],b[maxn],s[maxn];
bool can[maxn],f[maxn];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void merge(int x,int y)
{
int xx=find(x),yy=find(y);
if(xx!=yy)fa[yy]=xx;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();
for1(i,n*)fa[i]=i;
for1(i,n)
{
int x=read();
while(x){can[x]=;x=read();};
for1(j,n)
{
if(!can[j]&&j!=i)
{
if(find(j)==find(i)||find(j+n)==find(i+n))
{printf("No solution\n");return ;}
merge(i,j+n);
merge(j,i+n);
}
can[j]=;
}
}
for1(i,n)if(find(i)==find(i+n)){printf("No solution\n");return ;}
for1(i,n)s[find(i)]++;
for1(i,n)can[i]=;
for1(i,n)
for1(j,n)
if(find(i)==find(j+n))
{
int x=find(i),y=find(j);
b[min(x,y)]=max(x,y);
can[x]=can[y]=;
}
f[]=;
for1(i,n)
if(s[i])
{
if(can[i])
{
for3(j,n-s[i],)
if(f[j])f[j+s[i]]=;
}
else if(b[i])
{
for3(j,n,)
if(f[j])
{
f[j]=;
if(j+s[i]<=n)f[j+s[i]]=;
if(j+s[b[i]]<=n)f[j+s[b[i]]]=;
}
}
}
int ans=n,x=,y=n;
for1(i,n)
if(f[i])
{
int j=n-i;
if(abs(i-j)<ans)ans=abs(i-j),x=i,y=j;
}
printf("%d %d\n",min(x,y),max(x,y));
return ;
}
C.小Z的神奇数列
题目:http://www.luogu.org/problem/show?pid=U129
题解:SXBK的出题人,硬是把我的线段树卡到和暴力一个分T_T
线段树的做法应该是显然的吧,先将数组排序,然后每次二分到要删的位置,线段树单点修改一下。
不知道出题人的标程是什么神奇的做法。
代码:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 1000000+10000
#define maxm 5000000+10000
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 317847191
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
int n,m,a[maxn],mx[maxm],mi[maxm],ret[maxm];
bool b[maxn];
int find(int x)
{
int l=,r=n,mid;
while(l<=r)
{
mid=(l+r)>>;
if(a[mid]>x||(a[mid]==x&&b[mid]))r=mid-;
else l=mid+;
}
b[l]=;
return l;
}
inline void pushup(int k)
{
mx[k]=max(mx[k<<],mx[k<<|]);
mi[k]=min(mi[k<<],mi[k<<|]);
ll tmp=ret[k<<];
tmp=(tmp*ret[k<<|])%mod;
ret[k]=tmp;
}
inline void build(int k,int l,int r)
{
int mid=(l+r)>>;
if(l==r){mx[k]=mi[k]=ret[k]=a[l];return;}
build(k<<,l,mid);build(k<<|,mid+,r);
pushup(k);
}
inline void del(int k,int l,int r,int x)
{
int mid=(l+r)>>;
if(l==r){mx[k]=-inf;mi[k]=inf;ret[k]=;return;}
if(x<=mid)del(k<<,l,mid,x);else del(k<<|,mid+,r,x);
pushup(k);
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();m=read();
for1(i,n)a[i]=read();
sort(a+,a+n+);
for1(i,n)b[i]=;
build(,,n);
ll ans,x,y;
while(m--)
{
char ch[];
scanf("%s",ch);
if(ch[]=='D')del(,,n,find(read()));
else if(ch[]=='B')printf("%d\n",mx[]);
else if(ch[]=='S')printf("%d\n",mi[]);
else if(ch[]=='M')
{
for(ans=,x=mx[],y=mi[];y;y>>=,x=(x*x)%mod)
if(y&)ans=(ans*x)%mod;
printf("%d\n",ans);
}
else printf("%d\n",ret[]);
}
return ;
}
D.小Z的迷之阶梯
题目:http://www.luogu.org/problem/show?pid=U130
题解:出题人的声明就是在告诉我们这是道大水题吧。。。
n=200的数据范围很容易让我们想到n^3的算法,枚举上一个点o(n),枚举从该点向下退的次数o(n),
状态数o(n),n^3水过。。。
代码:
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 100000
#define maxm 500+100
#define eps 1e-10
#define ll long long
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
int n,a[maxn],f[maxn];
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();
for1(i,n)a[i]=read();
f[]=;
for2(i,,n)f[i]=inf;
for2(i,,n)
for1(j,i-)
for0(k,j-)
if(a[j-k]+(<<k)>=a[i])
f[i]=min(f[i],f[j]+k+);
printf("%d\n",f[n]==inf?-:f[n]);
return ;
}
CONTEST36 小Z的模拟赛(2)的更多相关文章
- 小X归来 模拟赛1 解析
Problem1 单峰 小X 归来后,首先对数列很感兴趣.他想起有1类特殊的数列叫单峰数列. 我们说一个数列 {ai} 是单峰的,当且仅当存在一个位置 k 使得 ai < ai+1(i < ...
- 【20170521校内模拟赛】热爱生活的小Z
学长FallDream所出的模拟赛,个人感觉题目难度还是比较适中的,难度在提高+左右,可能比较接近弱省省选,总体来讲试题考查范围较广,个人认为还是很不错的. 所有试题如无特殊声明,开启-O2优化,时限 ...
- 【20170920校内模拟赛】小Z爱学习
所有题目开启-O2优化,开大栈空间,评测机效率为4亿左右. T1 小 Z 学数学(math) Description 要说小 Z 最不擅长的学科,那一定就是数学了.这不,他最近正在学习加法运算.老 ...
- 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物
T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...
- 【0521模拟赛】小Z爱数学
题目描述 小Z想求F(n,k),F(n,k)表示n的所有因数pi中,满足n/pi <= k 的和. 小Z发现还是很水,所以他决定加大难度. 求 小Z还准备了很多个询问.现在你来解决一下吧. 输入 ...
- 【0521模拟赛】小Z爱划水
题目描述 小Z和其它机房同学都面临一个艰难的抉择,那就是 要不要划水? 每个人都有自己的一个意见,有的人想做题,有的人想划水. 当然,每个人只能选择一个事情做.如果一个人做的事情和他想做的不同,那么他 ...
- 小奇模拟赛9.13 by hzwer
2015年9月13日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿(explo) [题目背景] 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞 ...
- Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
小明用积木搭了一个城堡. 为了方便,小明在搭的时候用的是一样大小的正方体积本,搭在了一个 n 行 m 列的方格图上,每个积木正好占据方格图的一个小方格. 当然,小明的城堡并不是平面的,而是立体的.小明 ...
- Java 第十一届 蓝桥杯 省模拟赛 小明植树(DFS)
小明植树 题目 问题描述 小明和朋友们一起去郊外植树,他们带了一些在自己实验室精心研究出的小树苗. 小明和朋友们一共有 n 个人,他们经过精心挑选,在一块空地上每个人挑选了一个适合植树的位置,总共 n ...
随机推荐
- 小结OC中Retain cycle(循环引用)
retain cycle 的产生 说到retain cycle,首先要提一下Objective-C的内存管理机制. 作为C语言的超集,Objective-C延续了C语言中手动管理内存的方式,但是区别于 ...
- hadoop 常用命令
hdfs dfs -mkdir -p /usr/input/hot hdfs dfs -ls / hdfs dfs -ls /usr/input hdfd dfs -cat /usr/ouput/ho ...
- [Qt] qtcreator 中打开console
(1) qtcreator-->左侧Projects-->Run-->中间的checkbox (Run in terminal)打上勾 (2) 在项目的.pro文件中加上 " ...
- Zookeeper为什么总是奇数个
zookeeper有这样一个特性: [集群中只要有超过过半的机器是正常工作的,那么整个集群对外就是可用的] 也就是说如果有2个zookeeper,那么只要有1个死了zookeeper就不能用了,因为1 ...
- HBase的rowkey的设计原则
HBase是三维有序存储的,通过rowkey(行键),column key(column family和qualifier)和TimeStamp(时间戳)这个三个维度可以对HBase中的数据进行快速定 ...
- 在jsp页面上直接打开PDF文件
1.在不需要使用插件,直接打开通过链接方式打开 <%@ page language="java" import="java.util.*,java.io.*&quo ...
- 用GDB调试多进程程序
在子进程中sleep.然后attach上去. gdb --pid=123456 ps出子进程的id,gdb attach 进程号. http://www.ibm.com/developerworks/ ...
- C#使用 SQLite 数据库 开发的配置过程及基本操作类,实例程序:工商银行贵金属行情查看小工具
--首发于博客园, 转载请保留此链接 博客原文地址 本文运行环境: Win7 X64, VS2010 1. SQLite 的优点: SQLite 是一款轻型数据库,开发包只有十几M, 相对于 MSS ...
- gcc总结【基本用法】【选项】【动静态库】(转)
1.////////////////////////////////////////////////////////////////////////////////////////////////// ...
- 定时改变App主题的方案
1.将接口返回的图片缓存到本地,由于写data到本地是耗时操作,为了不阻塞主线程,可开启子线程来做此操作 dispatch_queue_t queue = dispatch_queue_create( ...