4.21小练

Mutual Training for Wannafly Union #3 & 4

我不知道我以后还记不记得补题。。。我只能尽量当天睡觉前能补多少就补多少,时间总是不够用,脑子更不够用orz

题目链接:https://vjudge.net/contest/159576#overview

A - Dungeon Trap     [ UVALive – 7220 ]  【最短路bfs】

//yy:练题时都没看这题,看题目就以为很难。。。晚上补 的时候发现居然是最短路,奥妙重重。。。

题意:0表示障碍,要将非0数转化成0(会花费这个数的值)使得A和B不连通(该题连通为四连通),问最大花费多少。

看着题解做的,枚举最后一个放置障碍的点,则ans=max(ans,sum-(从A到这个点的距离+从B到这个点的距离-2*这个点的权值));

//补题:AC  by  lyy:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<limits.h>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
const int N = 105;
const int inf = 0x3f3f3f3f;
int n, m;
int sum;
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
char s[N][N];
int d[N][N][2];
int ans;
int ax, ay, bx, by;
bool check(int x, int y) {
    if(x < 0 || x >= n || y < 0 || y >= m)
        return false;
    if(s[x][y] == '0')
        return false;
    return true;
}
struct node {
    int x, y;
};
void bfs(int x, int y, int id) {
    queue<node> q;
    d[x][y][id] = 0;
    q.push(node{x, y});
    while(!q.empty()) {
        node t = q.front(); q.pop();
        for(int i = 0; i < 4; ++i) {
            int xx = t.x + dx[i];
            int yy = t.y + dy[i];
            int w = s[xx][yy]-'0';
            if(check(xx, yy)) {
                if(d[xx][yy][id] > d[t.x][t.y][id] + w) {
                    d[xx][yy][id] = d[t.x][t.y][id] + w;
                    q.push(node{xx, yy});
                }
            }
        }
    }
}
int main(){
    int t;
    int i, j, k;
    scanf("%d",&t);
    for(k = 1; k <= t; ++k) {
        CLR(d, inf);
        scanf("%d%d", &n, &m);
        sum = 0;
        for(i = 0; i < n; ++i) {
            scanf("%s", s[i]);
            for(j = 0 ; j < m; ++j) {
                if(s[i][j] == 'A') {
                    ax = i; ay = j;
                }
                else if(s[i][j] == 'B') {
                    bx = i; by = j;
                }
                else {
                    sum += s[i][j] - '0';
                }
            }
        }
        bfs(ax, ay, 0);
        bfs(bx, by, 1);
        ans = 0;
        for(i = 0; i < n; ++i) {
            for(j = 0; j < m; ++j) {
                if(s[i][j] >= '1' && s[i][j] <= '9') {
                    if(d[i][j][0] != inf && d[i][j][1] != inf) {
                        int c = s[i][j] - '0';
                        ans = max(ans, sum-d[i][j][0]-d[i][j][1]+2*c);
                    ]
                }
            }
        }
        printf("Case #%d: %d\n", k, ans);
    }
    return 0;
}

B - Pigeonhole Tower   [ SPOJ – PHT ] 【二分】

题意:求用n根木棒能搭出多少层

第一层3根,第二层5,第三层7.。。。2*n+1.。。。。。。二分数量

//AC  by  lwq:

#include<stdio.h>
#include<algorithm>
using namespace std;
long long int q[1000000]; 
int main()
{
    int T;
    scanf("%d",&T);
    q[1]=3;
    int t=0;
    for(int i=2;i<=1000000;i++)
    {
        q[i]=q[i-1]+2*i+1;
    }
    while(T--)
    {
        t++;
        long long int n;
        scanf("%lld",&n);
        long long int L=1;
        long long int R=1000000;
        long long int MID=(L+R)/2;
        while(L+1<R)
        {
            if(n>=q[MID])
            {
                L=MID;
            }
            else
            R=MID;
            
            MID=(L+R)/2;
        }
        if(n<3)
        MID=0;
        printf("Case %d: %lld\n",t,MID);
    //    printf("%")
    }
    return 0;
}

C - Interesting Numbers  [ SPOJ – INUM ]  【二分】

题意:求分别有几对数满足差值绝对值最大和最小。

//AC  by  kn:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <climits>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 100;
ll a[maxn];

int main()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    ll mi = LONG_LONG_MAX;
    ll ma = LONG_LONG_MIN;
    sort(a, a + n);
    for(int i = 1; i < n; ++i) {
        mi = min(mi, a[i] - a[i - 1]);
    }
    ma = a[n - 1] - a[0];
    ll ans_mi = 0;
    ll ans_ma = 0;
    for(int i = 0; i < n; ++i) {
        ans_mi += (upper_bound(a + i + 1, a + n, a[i] + mi) - lower_bound(a + i + 1, a + n, a[i] + mi));
        ans_ma += (upper_bound(a + i + 1, a + n, a[i] + ma) - lower_bound(a + i + 1, a + n, a[i] + ma));
    }
    //cout << mi << " " << ma << endl;
    cout << ans_mi << " " << ans_ma << endl;
    return 0;
}

/*
5
0 0 2 0 0
*/

D – SubXor   [SPOJ – SUBXOR]

//yy:讨论了一会儿,我猜要用前缀树什么的,要不然超时,,然后大家都不会数据结构,然后就没有然后了orz,改天再补。。。

E – Guards   [UVALive – 5813]

//yy:就看懂了题意,没想出思路orz,很好玩,看题目发现构成一个矩形时就是一个集合,其他又是一个集合,然后想搜索,不会,也想不出怎么安排棋子;想了找规律,感觉也找不到;想了图论,也没想出什么,毕竟图论我感觉自己连基本概念都很多不知道;想了DP然后就不敢再想了。。。。放弃orz,改天补。。。

F - Extremely Lagged Fibonacci   [SPOJ – EXLAGFIB]

//yy:感觉太数学,再次放弃,害怕orz

G - Smile House   [CodeForces – 147B]

//yy:我看完这题突然想到floyd,dp之类的,但是不知道具体怎么处理,又放弃了orz,改天再补

H - Renting Bikes   [CodeForces – 363D]  【贪心,二分】

题意:已知每辆车的价格和人有的钱数和共享资金,每人最多买一辆车,问最多能买多少车以及私人花费的最多钱数。

题解:二分买车的数量,用最有钱的mid个人买最便宜的mid辆车。

//yy:二分折腾了好久orz结果最后细节没处理好一直WA,,二分求和时忘记改long long了。。

补题:AC  by  lyy:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<limits.h>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int n, m, k;
int a[N], b[N];
bool cmp(int x, int y) { return x > y; }
int main(){
    int i, j;
    scanf("%d%d%d", &n, &m, &k);
    for(i = 0; i < n; ++i) scanf("%d", &a[i]);//人有的钱
    for(i = 0; i < m; ++i) scanf("%d", &b[i]);//车的价格
    sort(a, a+n, cmp);
    sort(b, b+m);
    int l = 0, r = min(n, m);
    while(l < r) {//二分买车的数量
        int mid = (l + r + 1) >> 1;
        ll s = 0;
        for(int i = 0; i < mid; ++i) {
            if(a[i] < b[mid-1-i]) {
                s += b[mid-1-i] - a[i];
            }
        }
        if(s > k) r = mid-1;
        else l = mid;
    }
    printf("%d ", r);
    ll s = 0;
    for(i = 0; i < r; ++i) {
        s += b[i];
    }
    s -= k;
    if(s < 0) s = 0;
    printf("%lld\n", s);
    return 0;
}

I - Greg's Workout  [CodeForces – 255A]  【水题】

//AC  by  lyy:我觉得自己好水啊、、、

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<limits.h>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
const int N = 1e5;
const int mod = 1e9+7;
int a[30];
int main() {
    int n;
    scanf("%d", &n);
    int i, j;
    int x = 0, y = 0, z = 0;
    for(i = 0; i < n; ++i) {
        scanf("%d", &a[i]);
        if(i % 3 == 0) {x += a[i];}
        else if(i % 3 == 1) {y+=a[i];}
        else z+=a[i];
    }
    if(x >= y ) {
        printf("%s\n", x > z ? "chest" : "back");
    }
    else printf("%s\n", y > z ?  "biceps" : "back");
    return 0;
}

J - MUH and Cube Walls  [CodeForces – 471D]   【KMP】

题解:将幅度记录(就是相邻两数的差值),再KMP。

//AC  by  lyy:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<limits.h>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
const int N = 2e5+5;
const int mod = 1e9+7;
double eps = 1e-8;
int n, m;
int ans;
int a[N], b[N];

int nex[N];
void Next() {
    int i, j;
    j = nex[0] = -1;
    i = 0;
    while(i < m) {
        while(-1 != j && b[i] != b[j])
            j = nex[j];
        nex[++i] = ++j;
    }
}
void kmp(){
    int i = 0, j = 0;
    Next();
    while(i < n){
        if(j == -1 || a[i] == b[j]){
            i++; j++;
        }
        else
            j = nex[j];
        if(j == m) {
            ans++;
        }
    }
}

int main(){
    int i, j;
    scanf("%d%d", &n, &m);
    for(i = 0; i < n; ++i) scanf("%d", &a[i]);
    for(i = 0; i < m; ++i) scanf("%d", &b[i]);
    if(m == 1) { printf("%d\n", n); return 0; }

    for(i = 0; i < n-1; ++i) {
        a[i] = a[i+1] - a[i];
    }
    for(j = 0; j < m-1; ++j) {
        b[j] = b[j+1] - b[j];
    }
    ans = 0;
    --n, --m;
    kmp();
    printf("%d\n", ans);
    return 0;
}

K – Reclamation   [CodeForces – 325D]   【并查集】

//yy:kn说这题他去年听学姐讲过但是没在意听,然后开始想思路,说先在右边加上最左边一列,再在两边设两个源点并分别把两边的格子连接,然后每放一个障碍就检查其周围八个格子是否有跟两个源点连接,如果有就不能放这个障碍……总之就是,只要障碍左右都连通了,那么圆柱的上顶和下底就会不连通,就不能放这个障碍,,然后他敲了发并查集没过,然后我们又挂了orz

L - Crazy Town   [CodeForces – 499C]   【几何】

题意:有很多直线会把平面划分成很多块,给出直线方程的系数,起点和终点坐标,问最少走过几块可以从起点到终点

题解:分别把起点和终点代入每个直线方程,判断两点是否在直线两侧,是的话答案加一。

//yy:把long long改成了double就过了、、水题我总能以各种姿势先WA一下。。

AC  by  lyy:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<limits.h>
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
const int N = 1e5;
const int mod = 1e9+7;
double eps = 1e-8;
double x1, y1, x2, y2;
int main() {
    int n;
    scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
    scanf("%d", &n);
    int ans = 0;
    while(n--) {
        double a, b, c;
        scanf("%lf%lf%lf", &a, &b, &c);
        if((a*x1+b*y1+c) * (a*x2+b*y2+c) < eps)
            ans++;
    }
    printf("%d\n", ans);
    return 0;
}
posted @ 2017-04-22 00:54  GraceSkyer  阅读(275)  评论(0编辑  收藏  举报

~~~~~~ACM大牛语录,激励一下~~~~~~

为了世界的和平,为了女生的安全,我拼命做题,做题,做题!

用最短的时间,刷最多的题!

给我一滴泪,我就看到了你全部的海洋!

seize the hour, seize the day.

人生难免有无奈,幸福走远了,或是感叹幸福来迟了.其实我一直相信,无论手中的幸福是多么微不足道的感觉,我会把握住那每一分,每一秒,当幸福依旧像那百鸟般飞逝,终究无法掌握时,我会感谢它,曾经降临过!

A自己的题,让别人郁闷去吧

WA肠中过,AC心中留 TLE耳边过,AC特别牛

天然的悲苦和伤逝,过去有过,以后还会有

^*^一步一步往上爬^*^

AC就像练级,比赛就像PK. 练级不如PK好玩

其实,世上本没有ACM,AC的人多了,也便有了!

AC无止尽~ Seek you forever~

找呀找呀找水题,找到一个AC一个呀!

AC是检验程序的唯一标准。

真的猛士,敢于直面惨淡的人生,敢于正视淋漓的鲜血……