标签:线段 而且 为什么 code 慢慢 stream check 题目 --
巧克力棒(chocolate)
Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 找到了一根巧克力棒,但是这根巧克力棒太长了, LYK 无法一口吞进去。
具体地,这根巧克力棒长为 n,它想将这根巧克力棒折成 n 段长为 1 的巧克力棒,然后
慢慢享用。
它打算每次将一根长为 k 的巧克力棒折成两段长为 a 和 b 的巧克力棒,此时若 a=b,则
LYK 觉得它完成了一件非常困难的事,并会得到 1 点成就感。
LYK 想知道一根长度为 n 的巧克力棒能使它得到最多几点成就感。
输入格式(chocolate.in)
第一行一个数 n。
输出格式(chocolate.out)
一个数表示答案。
输入样例
7
输出样例
4
数据范围
对于 20%的数据 n<=5。
对于 50%的数据 n<=20。
对于 80%的数据 n<=2000。
对于 100%的数据 n<=1000000000。
样例解释
将 7 掰成 3+4,将 3 掰成 1+2,将 4 掰成 2+2 获得 1 点成就感,将剩下的所有 2 掰成 1+1
获得 3 点成就感。总共 4 点成就感。
/*贪心,尽量使长度向2^?靠近*/ #include<cstdio> #include<iostream> #define N 35 using namespace std; int a[N],b[N],num,n,ans; void dfs(int x) { if(x==1)return; for(int i=num;i>=1;i--) if(x>=a[i]) { if(x==a[i]) { ans+=x-1; return; } ans+=a[i]-1; dfs(x-a[i]); break; } } int main() { //freopen("chocolate.in","r",stdin); //freopen("chocolate.out","w",stdout); scanf("%d",&n); for(int i=2;i<=n;i*=2) a[++num]=i; dfs(n); printf("%d",ans); return 0; }
LYK 快跑! (run)
Time Limit:5000ms Memory Limit:64MB
题目描述
LYK 陷进了一个迷宫!这个迷宫是网格图形状的。 LYK 一开始在(1,1)位置,出口在(n,m)。
而且这个迷宫里有很多怪兽,若第 a 行第 b 列有一个怪兽,且此时 LYK 处于第 c 行 d 列,此
时这个怪兽对它的威胁程度为|a-c|+|b-d|。
LYK 想找到一条路径,使得它能从(1,1)到达(n,m),且在途中对它威胁程度最小的怪兽的
威胁程度尽可能大。
当然若起点或者终点处有怪兽时,无论路径长什么样,威胁程度最小的怪兽始终=0。
输入格式(run.in)
第一行两个数 n,m。
接下来 n 行,每行 m 个数,如果该数为 0,则表示该位置没有怪兽,否则存在怪兽。
数据保证至少存在一个怪兽。
输入格式(run.out)
一个数表示答案。
输入样例
3 4
0 1 1 0
0 0 0 0
1 1 1 0
输出样例
1
数据范围
对于 20%的数据 n=1。
对于 40%的数据 n<=2。
对于 60%的数据 n,m<=10。
对于 80%的数据 n,m<=100。
对于 90%的数据 n,m<=1000。
对于另外 10%的数据 n,m<=1000 且怪兽数量<=100
/* 典型的二分答案,但是第一遍预处理没处理好,90分,TLE 其实只要把这些点入队,BFS一遍就行了 */ #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #define N 1010 using namespace std; int a[N][N],b[N][N],n,m,num,qx[N*N],qy[N*N],vis[N][N]; int ax[4]={0,0,1,-1}; int ay[4]={1,-1,0,0}; bool check(int limit) { memset(vis,0,sizeof(vis)); memset(qx,0,sizeof(qx)); memset(qy,0,sizeof(qy)); int head=0,tail=1; qx[1]=1;qy[1]=1;vis[1][1]=1; while(head<tail) { ++head;int nx=qx[head],ny=qy[head]; for(int i=0;i<4;i++) { int xx=nx+ax[i],yy=ny+ay[i]; if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!vis[xx][yy]&&!a[xx][yy]&&b[xx][yy]>=limit) { ++tail;qx[tail]=xx;qy[tail]=yy;vis[xx][yy]=1; if(xx==n&&yy==m)return true; } } } return false; } void BFS() { int head=0,tail=num; while(head<=tail) { ++head;int nx=qx[head],ny=qy[head]; for(int i=0;i<4;i++) { int xx=nx+ax[i],yy=ny+ay[i]; if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&!b[xx][yy]&&!a[xx][yy]) { b[xx][yy]=b[nx][ny]+1; ++tail;qx[tail]=xx;qy[tail]=yy; } } } } int main() { //freopen("run.in","r",stdin); //freopen("run.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&a[i][j]); if(a[i][j]){qx[++num]=i;qy[num]=j;} } if(a[1][1]||a[n][m]) { printf("0"); return 0; } BFS(); int l=0,r=N*N,ans=0; while(l<=r) { int mid=(l+r)/2; if(check(mid)) { l=mid+1; ans=mid; } else r=mid-1; } printf("%d",ans); return 0; }
仙人掌(cactus)
Time Limit:1000ms Memory Limit:64MB
题目描述
LYK 在冲刺清华集训( THUSC)!于是它开始研究仙人掌?,它想来和你一起分享它最近
研究的结果。
如果在一个无向连通图中任意一条边至多属于一个简单环(简单环的定义为每个点至多
经过一次),且不存在自环,我们称这个图为仙人掌。
LYK 觉得仙人掌还是太简单了,于是它定义了属于自己的仙人掌。
定义一张图为美妙的仙人掌,当且仅当这张图是一个仙人掌且对于任意两个不同的点 i,j,
存在一条从 i 出发到 j 的路径,且经过的点的个数为|j-i|+1 个。
给定一张 n 个点 m 条边且没有自环的图, LYK 想知道美妙的仙人掌最多有多少条边。
数据保证整张图至少存在一个美妙的仙人掌。
输入格式(cactus.in)
第一行两个数 n,m 表示这张图的点数和边数。
接下来 m 行,每行两个数 u,v 表示存在一条连接 u,v 的无向边。
输出格式(cactus.out)
一个数表示答案
输入样例
4 6
1 2
1 3
1 4
2 3
2 4
3 4
输出样例
4
样例解释
选择边 1-2,1-3,2-3,3-4,能组成美妙的仙人掌,且不存在其它美妙仙人掌有超过 4 条
边。
数据范围
对于 20%的数据 n<=3。
对于 40%的数据 n<=5。
对于 60%的数据 n<=8。
对于 80%的数据 n<=1000。
对于 100%的数据 n<=100000 且 m<=min(200000,n*(n-1)/2)。
/* 首先这n个点应该全选(确实不知道为什么) 由题意可知,一定存在一条连接i与i+1的边,因为只存在一个简单环,所以除了i到i+1的边之外,只能有一条边覆盖i到i+1这个位置,这样就转成了线段覆盖问题。 */ #include<cstdio> #include<iostream> #include<algorithm> #define N 100010 using namespace std; int n,m; struct node { int x,y; };node e[N*2]; bool cmp(const node&s1,const node&s2) { return s1.y<s2.y; } int main() { //freopen("cactus.in","r",stdin); //freopen("cactus.out","w",stdout); scanf("%d%d",&n,&m); int t=0; for(int i=1;i<=m;i++) { int x,y;scanf("%d%d",&x,&y); if(x>y)swap(x,y); if(x+1!=y)e[++t].x=x,e[t].y=y; } sort(e+1,e+t+1,cmp); int tot=0,p=0; for(int i=1;i<=t;i++) if(e[i].x>=p)p=e[i].y,tot++; printf("%d",tot+n-1); return 0; }
标签:线段 而且 为什么 code 慢慢 stream check 题目 --
原文地址:http://www.cnblogs.com/harden/p/6034991.html