Xth and his rabbit
——by xth_幻
题目名称 | Xth的第12枚硬币 | Xth的玫瑰花 | Xth的旅行 | Xth砍树 |
输入文件 | Lsbm.in | Escape.in | Happy.in | Change.in |
输出文件 | Lsbm.out | Escape.out | Happy.out | Change.out |
测试点数目 | 10 | 10 | 10 | 10 |
测试点分数 | 10 | 10 | 10 | 10 |
题目类型 | 传统 | 传统 | 传统 | 传统 |
时间限制 | 1s | 1s | 1s | 1s |
空间限制 | 128M | 128M | 128M | 128M |
1.xth的第12枚硬币(coin.pas/c/cpp)
描述
传说xth曾经拥有11枚完全相同硬币(你懂得),不过今年呢,rabbit又送了他一枚硬币。这枚硬币和其他硬币外观相同,只有重量不同,或轻或重。Xth一不小心,将这枚特殊的硬币和其他硬币混在了一起。Rabbit知道后很生气,要他立刻把那枚硬币找出来,并且还要说出这枚硬币是轻还是重。可怜的Xth只有一架普通托盘天平,并且只能称量三次(每次称量,两边各四枚)。现在全部12枚硬币编号为A-L,现给出你三次称量的结果,请你帮xth找出那枚不一样的硬币。他一定会感谢你们滴~~~
输入格式(coin.in)
共三行,每行是由空格隔开的两个字符串,分别代表左右两盘的四个硬币,以及一个单词。’even’表示两侧重量相等,’up’表示右侧轻,’down’表示右侧重。
输出格式(coin.out)
一行,一个英文句子,指出那枚不一样的硬币以及它的轻重情况。
X is the counterfeit coin and it is light/heavy. (X表示硬币)
样例输入
ABCD EFGH even
ABCI EFJK up
ABIJ EFGH even
样例输出
K is the counterfeit coin and it is light.
注释
数据保证有且仅有一枚特殊的硬币,无矛盾情况出现。
#include <cstdio> #include <iostream> #include <cstring> using namespace std; string s[3][2],t; int g[3]; bool v[12]; int pos(char c,string s){ for (unsigned int i=0;i<s.size();i++){ if (s[i]==c) return i; } return -1; } bool check(char c,int p){ for (int i=0;i<3;i++){ if (g[i]==0 && (pos(c,s[i][0])!=-1 || pos(c,s[i][1])!=-1)) return false; if (g[i] && pos(c,s[i][1])==-1 && pos(c,s[i][0])==-1) return false; if (p==1 && ((g[i]==1 && pos(c,s[i][1])!=-1) || (g[i]==2 && pos(c,s[i][0])!=-1))) return false; if (p==0 && ((g[i]==1 && pos(c,s[i][0])!=-1) || (g[i]==2 && pos(c,s[i][1])!=-1))) return false; } return true; } int main(){ freopen("coin.in","r",stdin); freopen("coin.out","w",stdout); int T; scanf("%d",&T); while (T--){ memset(g,0,sizeof(g)); memset(v,0,sizeof(v)); for (int i=0;i<3;i++){ for (int j=0;j<2;j++){ cin>>s[i][j]; for (unsigned int k=0;k<s[i][j].size();k++) v[s[i][j][k]-'A']=1; } cin>>t; if (t=="even") g[i]=0; else if (t=="up") g[i]=1; else if (t=="down") g[i]=2; } for (int i=0;i<12;i++){ if (v[i]){ if (check(i+'A',0)){ printf("%c is the counterfeit coin and it is light.\n",i+'A'); return 0; }else if (check(i+'A',1)){ printf("%c is the counterfeit coin and it is heavy.\n",i+'A'); return 0; } } } } return 0; }
2.xth的玫瑰花(rose.pas/c/cpp)
描述
这天是rabbit的生日前夕,Xth来到花店,要给他的rabbit买玫瑰花,为了保证质量,他跟花店老板——小菜儿同学要求自己到花田采摘。小菜儿灰常希望早日见到暖熊(xth儿子的小名),于是他决定帮忙。
小菜儿告诉xth,花田是一个n*m的矩形区域,里面有红玫瑰和黑玫瑰两种玫瑰。Xth探明了每一块小区域内红玫瑰和黑玫瑰的种植量,并且还在花田的北边和西边分别设置了红玫瑰和黑玫瑰的收集站(地图上上北下南左西右东)。你的任务是设计一个运输线系统,使得运送的红玫瑰和黑玫瑰的总量最多。
运输线有两种,一种是东西向,一种是南北向。在一个格子内你能建造一种运输线,但不能两种都建。如果两个同类型运输线首尾相接,它们就可以被连接起来。
另外,这些玫瑰都十分不稳定,因此它们在运送过程中都不能拐弯。这就意味着如果某个格子上建有南北向运输线,但是它北边的格子建有东西向运输线。那么这条南北向运输线内运送的任何东西都将丢失。进一步地,运到红玫瑰收集点的黑玫瑰会丢失,运到黑玫瑰收集点的红玫瑰也会丢失。
【输入格式】(rose.in)
第一行包含两个整数n和m,表示花田大小。以下n行,每行m个整数,其中第i行第j个整数G[ i , j ] 描述各个格子上的黑玫瑰数量。接下来以类似的矩阵表示各个格子上的红玫瑰数量。
【输出格式】(rose.out)
仅一个整数, 表示最多可以采集到的红玫瑰和黑玫瑰的总量。
【输入样例】
4 4
0 0 10 9
1 3 10 0
4 2 1 3
1 1 20 0
10 0 0 0
1 1 1 30
0 0 5 5
5 10 10 10
【输出样例】
98
【数据范围】
对于30%的数据: 0<= n,m <=100;
对于100%的数据: 0<= n, m <=1000;
0<= G[ i, j ] <=1000.
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int n,m; int a[1100][1100]; int b[1100][1100]; int f[2][1100][1100]; int max(int a,int b){return a>b?a:b;} int main(){ freopen("rose.in","r",stdin); freopen("rose.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]); a[i][j]+=a[i][j-1]; } } for (int i=1;i<=n;i++){ for (int j=1;j<=m;j++){ scanf("%d",&b[i][j]); b[i][j]+=b[i-1][j]; } } for (int i=1;i<=n;i++){ for (int j=1;j<=m;j++){ f[0][i][j]=max(f[0][i-1][j],f[1][i-1][j])+a[i][j]; f[1][i][j]=max(f[0][i][j-1],f[1][i][j-1])+b[i][j]; } } printf("%d\n",max(f[0][n][m],f[1][n][m])); return 0; }
3.xth的旅行(trip.pas/c/cpp)
描述
毕业了,Xth很高兴,因为他要和他的rabbit去双人旅行了。他们来到了水城威尼斯。众所周知(⊙﹏⊙b汗),这里的水路交通很发达,所以xth和rabbit只好坐船穿梭于各个景点之间。但是要知道,rabbit是会晕船的,看到她难受,xth是会心疼的。
已知城市中有n个景点,这些景点之间有m条双向水路,在每条水路上航行时rabbit都会有一个“晕船值”。旅行时,xth会带着rabbit尽量选择晕船值小的路线旅行。但是rabbit也是有一定忍耐限度度的,如果晕船值超过了她的忍耐度,xth会果断决定放弃这条路线。
现在xth想进行若干次询问,给定rabbit的忍耐度,问还有多少对城市(x,y)间会存在可行的旅行路线(如果(x,z)和(z,y)可行,则(x,y)可行,也就是说连通性是可传递的)。
输入格式
第1行三个正整数n、m、Q,分别表示景点数量、水路数量和询问次数。
第2行到第m+1行每行三个正整数x、y、w,表示x号景点和y号景点之间有一条“晕船值”为w的双向水路。
第m+2行至第m+Q+1行,每行一个正整数k,表示询问中给定的rabbi忍耐度为k。
输出格式
共Q行,对于每次询问做出回答。
样例输入 Sample Input
5 5 2
1 2 1
2 3 2
3 4 1
4 5 4
5 1 1
1
2
样例输出 Sample Output
4
10
时间限制
各个测试点1s
【样例说明】
第一个询问:(1,2)、(1,5)、(2,5)、(3,4)。其中(2,5)的具体走法为:2-1-5
第二个询问:(1,2)、(1,3)、(1,4)、(1,5)、(2,3)、(2,4)、(2,5)、(3,4)、(3,5)、(4,5)。其中(4,5)的具体走法为:4-3-2-1-5
【数据规模】
对于20%的数据满足n<=20,m<=40,Q<=40;
对于40%的数据满足n<=1000,m<=2000,Q<=1000;
对于60%的数据满足n<=3000,m<=6000,Q<=200000;
对于100%的数据满足n<=100000,m<=200000,Q<=200000。其他数不超过10^9。
【细节提示】
1 给出的n个景点不一定全部互相连通,且两个景点之间可能存在多条道路,也可能存在某条边是从某景点出发回到他自己。
2 对于询问的结果可能很大,请注意使用适当的类型存储。
#include <cstdio> #include <iostream> #include <algorithm> #define INF 2000000000 using namespace std; int N,M,Q; struct edge{ int a,b,w; }e[400010]; struct Ask{ int id,x; long long ans; }a[400010]; int fa[200100]; long long size[200100]; int cmp1(edge a,edge b){return a.w<b.w;} int cmp2(Ask a,Ask b){return a.x<b.x;} int cmp3(Ask a,Ask b){return a.id<b.id;} int get(int x){ if (fa[x]==x) return x; fa[x]=get(fa[x]); return fa[x]; } int main(){ freopen("trip.in","r",stdin); freopen("trip.out","w",stdout); scanf("%d%d%d",&N,&M,&Q); for (int i=1;i<=M;i++){ scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].w); } for (int i=1;i<=Q;i++){ scanf("%d",&a[i].x); a[i].id=i; } for (int i=1;i<=N;i++){ fa[i]=i; size[i]=1; } e[M+1].w=INF; a[Q+1].x=INF; sort(e+1,e+1+M,cmp1); sort(a+1,a+1+Q,cmp2); long long ans=N; int i=1,j=1; while (i<=M || j<=Q){ if (e[i].w<=a[j].x){ int x=get(e[i].a); int y=get(e[i].b); if (x!=y){ ans+=2*(size[x]*size[y]); size[x]+=size[y]; size[y]=0; fa[y]=x; } i++; }else{ a[j].ans=(ans-N) / 2; j++; } } sort(a+1,a+1+Q,cmp3); for (int i=1;i<=Q;i++){ printf("%I64d\n",a[i].ans); } return 0; }
4.xth砍树(tree.pas/c/cpp)
描述
在一个凉爽的夏夜,xth和rabbit来到花园里砍树。为啥米要砍树呢?是这样滴,小菜儿的儿子窄森要出生了。Xth这个做伯伯的自然要做点什么。于是他决定带着rabbit去收集一些木材,给窄森做一个婴儿车……(xth早就梦想着要天天打菜儿他儿窄森的小pp,到时候在婴儿车里安装一个电子遥控手臂,轻轻一按,啪啪啪……“乌卡卡——”xth邪恶滴笑了,“不要告诉rabbit,她会说我缺德的……”xth如是说)。
花园里共有n棵树。为了花园的整体形象,rabbit要求xth只能在m个区域砍伐,我们可以将这m个区域看成m个区间,树的间距相等,都是1,我们将每个区间设为[x,y]。那么长度为k的区间中就有k棵树。树木的高度不等。现在xth想测量一下,每个区间树木砍伐后所得的木材量是多少,而且每次测量后他都会砍下标号为(x+y)div2的那棵作为纪念。以方便他安排人手。(同一个区间的树木可以重复砍伐,我们认为被砍过的树木高度为0)
每棵树的木材量=树的高度*3.14(注意是3.14不是pi)。
输入格式:
第一行,一个整数n。
第二行,共n个整数,表示每棵树的高度。
第三行,一个整数m,表示共m个区间。
以下m行,每个区间[x,y]的左右端点x、y。
输出格式
共m行,每行一个数,表示每个区间的木材量。
结果精确到小数点后两位。
输入样例:
5
1 2 3 4 5
2
1 4
2 4
输出样例:
31.40
21.98
数据规模:
对于30%的数据,有n<=5000,m<=5000;
对于100%的数据,有n<=200000,m<=200000;
样例解释:
第一次砍[1,4]的树后,森林变为:1 0 3 4 5
#include <cstdio> #include <algorithm> using namespace std; int N,M; int a[200100]; int s[200100]; int c[200100]; int lowbit(int x){ return (x & (x ^ (x-1))); } void change(int k,int x){ while (k<=N){ c[k]-=x; k+=lowbit(k); } } int getsum(int k){ int t=0; while (k>0){ t+=c[k]; k-=lowbit(k); } return t; } int main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); scanf("%d",&N); for (int i=1;i<=N;i++){ scanf("%d",&a[i]); s[i]+=s[i-1]+a[i]; } for (int i=1;i<=N;i++){ c[i]=s[i]-s[i-lowbit(i)]; } scanf("%d",&M); for (int i=1;i<=M;i++){ int x,y; scanf("%d%d",&x,&y); int sum=getsum(y)-getsum(x-1); double ans=sum*3.14; printf("%.2lf\n",ans); change((x+y)/2,a[(x+y)/2]); a[(x+y)/2]=0; } return 0; }