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;
}