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;
}
 
                    
                 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号