總結——關於2017 10 30測試的分析總結

NOIP 2017 模拟



10 30



T1:



题目:





——正解思路:

先把所有人升序排列,然后从大到小找到第一个满足 v[ i ] - v[ i - 1 ] > k 的地方,那么 i , i + 1 ....... N 都有可能获胜。

——我的乱搞

**没有乱搞,但题目表意很容易被理解错,差点被样例阴到。。。。


——tips:

做题时要瞪大双眼,,,






满载悲伤的代码:


#pragma GCC optimize("O3")

#include <fstream>
#include <algorithm>

using std::sort;

int v[100010];

inline void read (int &x) {
	x = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
}

int main () {
	int t, n, k, ans;
	read (t);
	while (t--) {
		read (n);
		read (k);
		for (int i = 1; i <= n; i++) read (v[i]);
		sort (v + 1, v + 1 + n);
		v[n + 1] = v[n];
		ans = 0;
		for (int i = n; v[i + 1] <= v[i] + k and i >= 1; --i, ++ans);
		printf ("%d\n", ans);
	}
	return 0;
}




T2:


题目:





——正解思路:

我们可以考虑 DP,dp[ i ][ j ] 表示已经拿走了 i 只鳕鱼,上一次拿走了 j 只鳕鱼,按照最优策略最终会比另一个人多拿多少。

s ( l , r ) 表示 l 到 r 只鱼的重量和。(可以前缀和优化)

dp ( i , j )  = max ( s ( j + 1 , i + j ) - dp ( i + j , j ) , s ( j + 1 , i + j + 1 ) - dp ( i + j + 1 , j + 1 ) )

复杂度 O ( N ^ 2 ) 。

我们显然可以注意到,第二位肯定不超过 N ^ 0.5,所以复杂度降到 O( N ^ 1.5 )

——我的乱搞:

本来想着打一个30分的暴力,,但莫名其妙的WA了,还WA的很远,,,,,这就很监介了,,,,



——tips:

本来想不出正解就已经很悲伤了,,,然后暴力还炸了。。。。蛤蛤蛤蛤。。。

怎么办,我也很绝望啊啊啊。



满载悲伤的代码:


#pragma GCC optimize("O3")

#include <iostream>
#include <fstream>
#include <cstring>

#define maxx(x, y) x < y ? x = y : 0

using namespace std;

int a[20020], r[20020] = {0, 1};
int f[20020][205];

inline void read (int &x) {
	x = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
}

int main () {
	for (int i = 1; i < 20010; i++)
		for (int j = 1; j <= r[i] and i + j < 20010; j++) {
			r[i + j] = max (r[i + j], j);
			r[i + j + 1] = max (r[i + j + 1], j + 1);
		}
	int t, n;
	read (t);
	while (t--) {
		read (n);
		for (int i = 1; i <= n; i++) read (a[i]), a[i] += a[i - 1];
		memset (f, 0, sizeof(f));
		for (int i = n; i >= 1; i--)
			for (int j = min (n + 1 - i, r[i]); j >= 1; j--) {
				f[i][j] = ~ (1 << 30);
				if (i + j <= n + 1) maxx (f[i][j], a[i + j - 1] - a[i - 1] - f[i + j][j]);
				if (i + j <= n) maxx (f[i][j], a[i + j] - a[i - 1] - f[i + j + 1][j + 1]);
			}
		std::cout<<f[1][1]<<'\n';
	}
	return 0;
}

uses math;
var
t, n, i, j : longint;
a, r : array [0..20010] of longint;
f : array [0..20010, 0..202] of longint;
begin
        r[1] := 1;
        for i := 1 to 20005 do begin
                j := 1;
                while (j <= r[i]) and (i + j < 20005) do begin
                        r[i + j] := max (r[i + j], j);
                        r[i + j + 1] := max (r[i + j + 1], j + 1);
                        inc (j);
                end;
        end;
        read (t);
        while t > 0 do begin
                dec (t);
                read (n);
                for i := 1 to n do begin
                        read (a[i]);
                        inc (a[i], a[i - 1]);
                end;
                fillchar (f, sizeof(f), 0);
                for i := n downto 1 do begin
                        for j := min (n + 1 - i, r[i]) downto 1 do begin
                                f[i, j] := not (1 shl 30);
                                if i + j <= n + 1 then
                                        if f[i, j] < a[i + j - 1] - a[i - 1] - f[i + j, j] then
                                                f[i, j] := a[i + j - 1] - a[i - 1] - f[i + j, j];
                                if i + j <= n then
                                        if f[i, j] < a[i + j] - a[i - 1] - f[i + j + 1, j + 1] then
                                                f[i, j] := a[i + j] - a[i - 1] - f[i + j + 1, j + 1];
                        end;
                end;
                writeln (f[1, 1]);
        end;
end.





T3:



题目:





——正解思路:

原题等价于求一条边在多少个三元环里面,对于一个含有轻点的三元环,会被轻点统计,所以对于一条边两个点都是重点,枚举另一个重点并检查是否构成环。

复杂度 O ( M ^ 1.5 )

——我的乱搞:

本来写了一个目测 N * M 的暴力,结果其实差不多接近正解,但被 vector 卡T了。。。。。。。


——tips:

感觉不会再爱 vector 了。。。。

乖乖用数组吧。。。。。。。。



满载悲伤的代码:


#pragma GCC optimize("O3")

#include <iostream>
#include <fstream>
#include <cstring>

int t, n, m, x, y, cnt, tri, pos;
long long ans;
int to[400040], next[400040], first[100010], in[100010], v[5000];
bool b[100010];

inline void read (int &x) {
	x = 0;
	char c = getchar();
	while (!isdigit(c)) c = getchar();
	while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
}

inline void add (int x, int y) {
	to[++cnt] = y;
	next[cnt] = first[x];
	first[x]  = cnt;
	++in[x];
}

int main () {
	read (t);
	while (t--) {
		read (n);
		read (m);
		ans = cnt = 0;
		memset (to, 0, sizeof(to));
		memset (in, 0, sizeof(in));
		memset (next, 0, sizeof(next));
		memset (first, 0, sizeof(first));
		for (int i = 1; i <= m; i++) {
			read (x);
			read (y);
			add (x, y);
			add (y, x);
		}
		for (int i = 1; i <= n; i++) if (in[i] >= 3) {
			memset (b, 0, sizeof(b));
			pos = 0;
			for (int j = first[i]; j; j = next[j]) {
				b[to[j]] = true;
				if (to[j] > i and in[to[j]] >= 3) v[++pos] = to[j];
			}
			for (int j = pos; j >= 1; j--) {
				tri = 0;
				for (int k = first[v[j]]; k; k = next[k]) if (b[to[k]]) ++tri;
				ans += 1ll * tri * (tri - 1) / 2;
			}
		}
		std::cout<<ans<<'\n';
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值