Codeforces Round #229 (Div. 2)

Problems
 
 
# Name    
A
standard input/output
1 s, 256 MB
Submit Add to favourites  x2312
B
standard input/output
1 s, 256 MB
Submit Add to favourites  x1776
C
standard input/output
1 s, 256 MB
Submit Add to favourites  x900
D
standard input/output
1 s, 256 MB
Submit Add to favourites  x625
E
standard input/output
1 s, 512 MB
Submit Add to favourites  x92
A题:Inna的房间里,有很多个闹钟,她一次可以关竖或横一整排闹钟,问最少要几次关完。
思路:找出横和竖线较少的就是答案。

B题:Inna和Dima演奏音乐给 Sereja听,ai代表音符,bi代表音符的和谐值,他们弹奏的音符不超过ai,如果能满足两人之和xi+yi=bi,那么Sereja的愉悦值会增加xi*yi,否则-1。
思路:如果能满足,肯定对半开是最好的,不能满足的情况为a[i]*2<b[i],注意a[i]是>=1的,所以b[i]为1实际上也是不行的,因为a[i]取不到0。

C题:Inna有一些糖果盒,1代表有糖果,0代表没有糖果,现在询问一个礼物盒区间[l,r],要使得这些盒子满足l-1+k,l-1+2k,l-1+3k...这些盒子有糖果,其余盒子都没有糖果,问需要几步(包括取出和放入)
思路:先预处理,由于k最多是10,所以实际上只要预处理以前k打头的情况,因为1+k和1实际上是等价的,然后开两个数组一个sum记录前i个有多少个1,一个s记录以k为开头的,前i个应有多少个1,那么我们询问[l,r]的时候,最终盒子肯定为(r - l + 1) / k个糖果。
所以答案为(sum[r]-sum[l] -  (s[r] - s[l]))+ (r - l + 1) / k - (s[r] - s[l]),注意一些下标的细节。

D题:Inna有k个糖果,在一个n*m平面上,她要从(1,1)移动糖果,使得总移动步数最少,并且使得每个糖果都能移动到一个合适的位置。求步数并输出移动路径。
思路:先是贪心的思想,步数要尽量少,横纵坐标之和-1即为步数,那么就按这排序,前k个就是我们要的目标位置,接着构造路径,既然已知目标位置,那么让每个先一直往下在一直往右移动就可以了。

E题:在一个n*m平面上,Inna进行w次操作,操作0表示在(x1,y1)到(x2,y2)的矩形中添加v个糖果,操作1表示询问(x1,y1)到(x2,y2)的矩形中的糖果数与该矩形4个角上对应矩形中的总糖果数的差。
思路:看到添加,询问自然就会想到树状数组,线段树,但是好像是二维的,实际上可以用一维的做法,把x和y分开来考虑,最后询问计算个数的时候,计算方式就如下图所示。下标还是有些细节要多注意。

代码:
A:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 105;
int n, visx[N], visy[N];

int main() {
    scanf("%d", &n);
    int x, y, xn = 0, yn = 0;
    while (n--) {
        scanf("%d%d", &x, &y);
        if (!visx[x]) {
            xn++;
            visx[x] = 1;
        }
        if (!visy[y]) {
            yn++;
            visy[y] = 1;
        }
    }
    int ans = (xn < yn ? xn : yn);
    printf("%d\n", ans);
    return 0;
}

B:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 100005;
__int64 a[N], b[N];
int n, i;
int main() {
    scanf("%d", &n);
    for (i = 0; i < n; i++)
        scanf("%I64d", &a[i]);
    for (i = 0; i < n; i++)
        scanf("%I64d", &b[i]);
    __int64 ans = 0;
    for (i = 0; i < n; i++) {
        if (a[i] * 2 < b[i]) ans--;
        else if (b[i] == 1) ans--;
        else ans += (b[i] / 2) * (b[i] - b[i] / 2);
    }
    printf("%I64d\n", ans);
    return 0;
}

C:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 100005;
int n, k, w, i, sum[15][N], s[N];//sum其实开1维就可以了,写得搓又长,其实可以写得更简略
char str[N];

int main() {
	scanf("%d%d%d", &n, &k, &w);
	scanf("%s", str + 1);
	for (i = 1; i <= n; i++) {
		s[i] = s[i - 1] + str[i] - '0';
	}
	for (i = 1; i <= k; i++) {
		for (int j = i - 1 + k; j <= n; j += k) {
			if (str[j] == '1') {
				sum[i][j] = sum[i][j - k] + 1;
			}
			else sum[i][j] = sum[i][j - k];
		}
	}
	int l,r;
	while (w--) {
		scanf("%d%d", &l, &r);
		int ll = l;
		l %= k; if (l == 0) l = k;
		int ss = sum[l][r] - sum[l][ll - 1];
		int sss = s[r] - s[ll - 1];
		int h = (r - ll + 1) / k;
		int ans = h - ss + (sss - ss);
		printf("%d\n", ans);
	}
	return 0;
}

D:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 55;
int n, m, k, i, j;
struct G {
    int x, y;
} g[N * N];

bool cmp(G a, G b) {
    return a.x + a.y < b.x + b.y;
}

int main() {
    scanf("%d%d%d", &n, &m, &k);
    int gn = 0;
    for (i = 1; i <= n; i++)
        for (j = 1; j <= m; j++) {
            g[gn].x = i; g[gn++].y = j;
        }
    sort(g, g + gn, cmp);
    int ans = 0;
    for (i = 0; i < k; i++)
        ans += g[i].x + g[i].y - 1;
    printf("%d\n", ans);
    for (i = k - 1; i >= 0; i--) {
        for (j = 1; j <= g[i].y; j++)
            printf("(1,%d) ", j);
        for (j = 2; j <= g[i].x; j++)
            printf("(%d,%d) ", j, g[i].y);
        printf("\n");
    }
    return 0;
}

E:
#include <stdio.h>
#include <string.h>

const int MAXN = 4 * 1000005;
__int64 bit1[2][MAXN], bit2[2][MAXN];

void insert(__int64 *bit, int x, __int64 value) {
    while (x < MAXN) {
        bit[x] += value;
        x += x&(-x);
    }
}

__int64 get(__int64 *bit, int x) {
    __int64 ans = 0;
    while (x > 0) {
        ans += bit[x];
        x -= x&(-x);
    }
    return ans;
}

void Insert(int id, int l, int r, __int64 value) {
    insert(bit1[id], l, value);
    insert(bit1[id], r + 1, -value);
    insert(bit2[id], l, -value * (l - 1));
    insert(bit2[id], r + 1, value * r);
}

__int64 Get(int id, int x) {
    return get(bit1[id], x) * x + get(bit2[id], x);
}

int n, m, w;

int main() {
    scanf("%d%d%d", &n, &m, &w);
    int v, x1, y1, x2, y2;
    __int64 value;
    while (w--) {
        scanf("%d%d%d%d%d", &v, &x1, &y1, &x2, &y2);
        if (v) {
            __int64 ans = Get(1, y2) - Get(1, y1 - 1) - (Get(0, n) - Get(0, x2) + Get(0, x1 - 1));
            printf("%I64d\n", ans);
        }
        else {
            scanf("%I64d", &value);
            Insert(0, x1, x2, value * (y2 - y1 + 1));
            Insert(1, y1, y2, value * (x2 - x1 + 1));
        }
    }
    return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值