NOIP 2023 摆烂记

前言

已经高三了,但是还是想玩一下,抽空写点题目,顺便记录一下。

【前情提要:本文的撰写具有滞后性,因此流失了大量细节。】

2023.9.16 2023.9.16 2023.9.16

初赛,完善程序做得稀烂,好在 60 + 60+ 60+ 还是过线了。真不敢相信今年浙江线会这么低,只有 50.5 p t s 50.5 \rm{pts} 50.5pts

2023.9.29 2023.9.29 2023.9.29

呃,高三牲的国庆只有 3 3 3 天。问老师要了题目,打长乐的模拟赛。

T1 \texttt{T1} T1 一看 1 0 9 10^9 109 的数据范围加 1 0 6 10^6 106 的询问就猜测是推出式子加上矩阵快速幂优化。手玩小数据推了半天,还很不要脸的用了一下 OEIS \texttt{OEIS} OEIS,发现 f n = f n − 1 + f n − 3 + 1 f_n = f_{n - 1} + f_{n - 3} + 1 fn=fn1+fn3+1,所以就有了一个 4 × 4 4 \times 4 4×4 的矩阵:
[ f [ n ] f [ n − 1 ] f [ n − 2 ] 1 ] = [ 1   0   1   1 1   0   0   0 0   1   0   0 0   0   0   1 ] n − 3 × [ f [ n − 1 ] f [ n − 2 ] f [ n − 3 ] 1 ] \left[ \begin{array}{ccc}f[n]\\f[n - 1]\\f[n - 2]\\1 \end{array} \right] = \left[ \begin{array}{ccc}1\ 0 \ 1 \ 1 \\ 1 \ 0 \ 0 \ 0 \\ 0 \ 1 \ 0 \ 0 \\ 0 \ 0 \ 0 \ 1 \end{array} \right] ^ {n - 3} \times \left[ \begin{array}{ccc}f[n - 1]\\f[n - 2]\\f[n - 3]\\1 \end{array} \right] f[n]f[n1]f[n2]1 = 1 0 1 11 0 0 00 1 0 00 0 0 1 n3× f[n1]f[n2]f[n3]1

算了一下时间复杂度是 O ( T × 4 3 × log ⁡ n ) O(T \times 4^3 \times \log n) O(T×43×logn),好像数据有点大,可能会被卡常,但是没管了先做后面的。

T2 \texttt{T2} T2 似乎是个简单题,就是求 A A A 中有多少段和 B B B 的长度相同且含 1 1 1 的个数相同。由于题目限制了询问串的总长,所以充分利用好根号这一分界线,小于的用记忆化的方式去算,大的直接暴力,时间复杂度 O ( n L ) O(n \sqrt{L}) O(nL )

T3 \texttt{T3} T3 染色,大概是要 dp \texttt{dp} dp,但是似乎不会。写了一个暴力外加颜色均相同的这一档的递推。

T4 \texttt{T4} T4 n n n 个数均分到 k k k 个集合中,保证每个集合中元素互异。设第 i i i 个集合中的极差为 s i s_i si,求 min ⁡ ( ∑ i = 1 k s i ) \min (\sum_{i = 1}^{k} s_i) min(i=1ksi)。这个暴力看上去也很难打,所以陷入沉思。就在我一直盯着 n ≤ 70 n \le 70 n70 的数据范围上时,突然想到了一种乱搞做法:就是每次打乱这 n n n 个数,然后按顺序塞入 k k k 个集合中,若所有集合合法,那么更新答案。不断循环最后加上一个卡时就行。试了一下能过样例,真棒!

预计得分: 80 + 100 + 30 + ? ? ? 80 + 100 + 30 + ??? 80+100+30+???

实际得分: 60 + 100 + 20 + 60 = 240 pts 60 + 100 + 20 + 60 = 240 \texttt{pts} 60+100+20+60=240pts

震惊,乱搞做法竟然获得了 60 60 60 的高分,这是好的。但是, T1 \texttt{T1} T1 被多卡了 20 20 20,以及 T3 \texttt{T3} T3 写了好长的递推的 10 pts 10 \texttt{pts} 10pts 好像错了没拿到分数。看了一下排名 rk   4 \texttt{rk 4} rk 4 还不错。

看了题解,第一题是对 4 3 4^3 43 的矩阵转移的优化,倍增预处理然后在询问里用 1 × 4 1 \times 4 1×4 4 × 4 4 \times 4 4×4 的矩阵更新。后面两题嘛,看了题解还是实现不出来 qwq。

2023.9.30 2023.9.30 2023.9.30

T1 \texttt{T1} T1 简单的模拟,本来想着线段树优化求和,但马上发现差分就行了,半小时内就码完了这题。好像还抢到了一血来着。

T2 \texttt{T2} T2 竟然做过,是 The Shortest Statement,最短路加最小生成树的好题!但是数据范围有些差异,赛时过于高兴的复制了当时的代码,没仔细看,所以最后因为数组越界 100 → 40 100 \to 40 10040

T3 \texttt{T3} T3 又是一道考察冒泡排序的深度理解的题目,很容易想到按照奇偶位处理,但是发现复杂度怎么搞都是 O ( n m log ⁡ n ) O(nm \log n) O(nmlogn),最后交了暴力上去。赛后订正发现题解的方法很妙,用桶记录数字,然后奇数 + 1 +1 +1,偶数 − 1 -1 1,这样就可转换为数据结构维护极值。

T4 \texttt{T4} T4 动归,转移方程很好列:

d p i = max ⁡ { d p j ∣ a i ≥ a j , 0 ≤ j ≤ i − 1 − ( i − j ) ( i − j − 1 ) 2 } + a i dp_i = \max \{dp_{j|a_i \ge a_j,0 \le j \le i - 1} - \dfrac{(i - j)(i - j - 1)}{2}\} + a_i dpi=max{dpjaiaj,0ji12(ij)(ij1)}+ai,答案的更新是 a n s = max ⁡ ( a n s , d p i − ( n − i + 1 ) ( n − i ) 2 ) ans = \max \left (ans,dp_i - \dfrac{(n - i + 1)(n - i)}{2}\right) ans=max(ans,dpi2(ni+1)(ni))。然后不太会斜率优化以及不太会 a i ≥ a j a_i \ge a_j aiaj 的处理,所以就实现了一个 O ( n 2 ) O(n^2) O(n2) 的朴素 dp \texttt{dp} dp。由于我并没有处理负数的情况,但是好像部分分的数据有误,所以我爆灵了。

最后得分: 100 + 40 + 30 + 0 = 170 100 + 40 + 30 + 0 = 170 100+40+30+0=170,排名 rk   15 \texttt{rk 15} rk 15。本来应该是: 100 + 100 + 30 + 20 = 250 100 + 100 + 30 + 20 = 250 100+100+30+20=250 的呜呜呜……

2023.10.01 2023.10.01 2023.10.01

T1 \texttt{T1} T1 稍作分析就发现这个概率并没什么实际的用处,能到达与根距离为 k k k 的结点的期望为 2 − k 2^{-k} 2k。直接遍历所有的根求解为 O ( n 2 ) O(n^2) O(n2),容易想到换根 dp \texttt{dp} dp f u = 2 s z u − 1 + ∑ v ∣ s o n u 2 s z u − s z v − 1 f v f_u = 2^{sz_u - 1} + \sum_{v \mid son_u} 2^{sz_u - sz_v - 1} f_v fu=2szu1+vsonu2szuszv1fv,时间复杂度就变为 O ( n ) O(n) O(n)。自己实现的时候直接处理了 2 − k 2^{-k} 2k 算期望,和标程的转移方程略有不同。

T2 \texttt{T2} T2 直接构造若干个完全图,一个完全图的三元环数为 C k 3 = k ( k − 1 ) ( k − 2 ) 6 C_k^3 = \dfrac {k(k - 1)(k - 2)}{6} Ck3=6k(k1)(k2)。因此从 500 500 500 开始向 1 1 1 开始遍历即可。简单题,并拿到了一血。

T3 \texttt{T3} T3 赛时在贪心还是动规之间徘徊。还是分析不到位,最后打了个暴力交上去,但是 WA \texttt{WA} WA 了。

T4 \texttt{T4} T4 不知怎的,写了一个模拟,也 WA \texttt{WA} WA 了。

最后得分: 100 + 100 + 0 + 0 = 200 100 + 100 + 0 + 0 = 200 100+100+0+0=200,排名 rk   10 \texttt{rk 10} rk 10

2023.10.15 2023.10.15 2023.10.15

打洛谷上的模拟赛,打得有点废, 100 + 8 + 25 + 0 = 133 100 + 8 + 25 + 0 = 133 100+8+25+0=133

T1 \texttt{T1} T1 想的 dp \texttt{dp} dp 一直假,直到机房大佬的点拨以后才勉强写出来。反正花费了很多很多时间。赛后看题解,发现 ST \texttt{ST} ST 表页行,反正赛时啥也不行。

T2 \texttt{T2} T2 暴力,然后润。赛后补题,其实也蛮好想的,就是基于二进制位的树上 dp \texttt{dp} dp,设 g [ u ] [ i ] [ 0 / 1 ] g[u][i][0/1] g[u][i][0/1] 表示以 $u $为根的子树内,所有断边方案中价值在二进制下第 i i i 位为 0 / 1 0/1 0/1 的不与 u u u 相连的联通块的价值乘积的和.

T3 \texttt{T3} T3 暴力大分讨,然后润。正解是区间 dp \texttt{dp} dp,时间复杂度 O ( T n 3 ) O(Tn^3) O(Tn3),看题解吧,思路就不写了。

T4 \texttt{T4} T4 没看,直接润。

2023.10.21 2023.10.21 2023.10.21

比赛日! rp++ \texttt{rp++} rp++

T1 \texttt{T1} T1 水题,直接暴力搜索,然后过大样例。

T2 \texttt{T2} T2 字符串消消乐,想了半天只会 O ( n 3 ) O(n^3) O(n3) 的区间 dp \texttt{dp} dp,之后一直没有进展。害,其实出考场才发现 O ( n 2 ) O(n^2) O(n2) 的做法也蛮好想的。当然,正解是线性做法,发现从 1 1 1 n n n 维护栈序列时,若对于某个时刻 l l l 和某个时刻 r r r,两种时刻的栈序列完全相同,那么说明子串 ( l + 1 , r ) (l+1,r) (l+1,r) 一定是可消除。

T3 \texttt{T3} T3 大模拟,写了半天放弃了最后一题,最后因为看错一丢丢题干,喜提 0   pts 0 \texttt{ pts} 0 pts。不说了,赛后写了 3.02 KB 3.02 \texttt{KB} 3.02KB 苟过了。放个代码纪念一下:

#include <bits/stdc++.h>
#define init(x) memset (x,0,sizeof (x))
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
using namespace std;
const int MAX = 1e5 + 5;
const int MOD = 1e9 + 7;
int n;ll p;//所有变量的内存指针 
struct ele //定义一个变量 
{
	ll len,ali_len;//占据空间 对齐要求 
	string ty,name;//类型 变量名称 
} ;
struct stct
{
	ll len,ali_len;
	string name;
	vector <ele> v;//记录结构体内的每一个变量 
	stct () {len = ali_len = 0;name = "";v.clear ();} 
} tot;//记录所有的变量的一个大结构体 
map <string,int> bs;//4 个基本类型
map <string,stct> ext;//自定义类型 
void init_basic ();
void calc (ll &p,ll x);
void op_one ();
void op_two ();
void op_three ();
void op_four ();
int main ()
{
//	freopen (".in","r",stdin);
//	freopen (".out","w",stdout);
	cin>>n;init_basic ();
	for (int i = 1;i <= n;++i)
	{
		int ty;cin>>ty;
		if (ty == 1) op_one ();
		if (ty == 2) op_two ();	
		if (ty == 3) op_three ();
		if (ty == 4) op_four ();
	} 
	return 0;
}
void init_basic () {bs["byte"] = 1;bs["short"] = 2;bs["int"] = 4;bs["long"] = 8;} 
void calc (ll &poi,ll ali) {poi = ceil ((long double) poi / ali) * ali;}//当前地址 对齐要求 
//tmp 表示新的结构体   nw 表示新的变量 
void op_one ()
{
	int k;stct tmp;cin>>tmp.name>>k;
	for (int i = 1;i <= k;++i)
	{
		ele nw;cin>>nw.ty>>nw.name;
		if (bs[nw.ty]) nw.len = nw.ali_len = bs[nw.ty];//基本类型 
		else nw.len = ext[nw.ty].len,nw.ali_len = ext[nw.ty].ali_len;//自定义类型 
		tmp.ali_len = max (tmp.ali_len,nw.ali_len);tmp.v.push_back (nw);//计算对齐要求 在结构体中加入变量 
		calc (tmp.len,nw.ali_len);tmp.len += nw.len;//地址偏移的处理 长度更新 
	}
	calc (tmp.len,tmp.ali_len);
	ext[tmp.name] = tmp;//加入一个新的结构体 
	printf ("%lld %lld\n",tmp.len,tmp.ali_len); 
} 
void op_two ()
{
	ele nw;ll ans = 0;cin>>nw.ty>>nw.name;
	for (ele x : tot.v) calc (ans,x.ali_len),ans += x.len;
	calc (ans,bs[nw.ty] ? bs[nw.ty] : ext[nw.ty].ali_len);
	tot.v.push_back ({bs[nw.ty] ? bs[nw.ty] : ext[nw.ty].len,bs[nw.ty] ? bs[nw.ty] : ext[nw.ty].ali_len,nw.ty,nw.name});//将新变量加入的总的结构体中 
	printf ("%lld\n",ans);
}
void op_three ()
{
	string s;stct tmp = tot;ll ans = 0;cin>>s;
	for (int i = 0,j;i < s.size ();i = j + 1)
	{
		j = i;
		while (j < s.size () && s[j] != '.') ++j;
		string nw = s.substr (i,j - i);//以 . 分隔层层取出变量 
		for (ele x : tmp.v)
		{
			calc (ans,x.ali_len);
			if (x.name == nw) {tmp = ext[x.ty];break;}//层层深入 
			ans += x.len;
		} 
	}
	printf ("%lld\n",ans);
}
void op_four ()
{
	stct tmp = tot;ll sum = 0,k,ok;cin>>k;
	while (1)
	{
		ok = 0;
		for (ele x : tmp.v)
		{
			calc (sum,x.ali_len);
			if (sum <= k && k < sum + x.len)//在某个变量的区间中 
			{
				if (bs[x.ty]) {ok = 1;break;}//是最小单元,说明存在解 
				tmp = ext[x.ty];//向内层走 
				ok = 2;break;
			}	
			sum += x.len;
			if (sum > k) {ok = 0;break;} 
		}
		if (!ok || ok == 1) break;
	}
	if (!ok) {puts ("ERR");return ;}
	sum = 0;tmp = tot;
	while (1)
	{
		for (ele x : tmp.v)
		{
			calc (sum,x.ali_len);
			if (sum <= k && k < sum + x.len)
			{
				cout<<x.name;
				if (bs[x.ty]) {puts ("");return ;} 
				tmp = ext[x.ty];cout<<".";
				break;
			}
			sum += x.len;
		}
	}
} 

T4 \texttt{T4} T4 其实但凡做了这题目多少也可得点分。(后悔.jpg)。树上的二分套二分,显然二分天数以及至少要中的时间,唯一的坑点就是可能爆 long   long \texttt{long long} long long

得分: 100 + 35 + 0 + 0 = 135 100 + 35 + 0 + 0 = 135 100+35+0+0=135。为什么要写大模拟!!!为什么不做 T4 \texttt{T4} T4!!!【所以依旧获得 2 = 2= 2=

2023.11.8 2023.11.8 2023.11.8

市一模考完,润到机房!(奈斯的安排,第三天上午就考完!【笑死我,有的人,在别人全考完的时候还没开始考……】)

PS \texttt{PS} PS:喜提年排 28 28 28 OI \texttt{OI} OI 助我一臂之力。】

下午做洛谷模拟赛。

T1 \texttt{T1} T1 数论题,翻译一下就是给长度为 n n n 的序列 a a a 和一个数 w w w,每次操作你可以选择一个 a i a_i ai 使得 a i = a i + 1 a_i = a_i + 1 ai=ai+1,至多操作 w w w 次,最大化 Π i = 1 w a i \Pi_{i = 1}^{w} a_i Πi=1wai。做法就是贪心选择最小值, O ( n 2 ) O(n^2) O(n2) 即可。

T2 \texttt{T2} T2 找规律(赛时没找到,寄),在直到规律后,代码短的离谱。

T3,T4 \texttt{T3,T4} T3T4 好像没做。

2023.11.12 − 14 2023.11.12-14 2023.11.1214

翘了运动会,打三套模拟赛,做 NOIP \texttt{NOIP} NOIP 最后的冲刺。反正打得不错,具体就不写了。

2023.11.18 2023.11.18 2023.11.18

比赛日。

8:30 \texttt{8:30} 8:30 开始比赛,用福昕阅读器解码 pdf \texttt{pdf} pdf 多次失败,后来说要从浏览器这里打开才行……

8:35 \texttt{8:35} 8:35 写完缺省,开始读题。似乎是模拟 + + + 图论 + + + 盲猜数据结构 + + + 盲猜数据结构/动态规划,猜的还挺准的。

8:45 \texttt{8:45} 8:45 开始写 T1 \texttt{T1} T1,真的是三年来最简单的签到题,记录一下最大最小值,然后直接 O ( n 2 ) O(n^2) O(n2) 判断即可。

9:00 \texttt{9:00} 9:00 写完,开始看 T2 \texttt{T2} T2,发现有 40   pts \texttt{40 pts} 40 pts 是送的,直接敲。然后开始想正解,其间一直没用想通一个能成环的样例,所以一直手模构造,好像花了很久,然后尝试写了代码,但是一直出不来。代码越改越乱,大样例全过不了,稍微有点慌。这时候大概已经 10:20 \texttt{10:20} 10:20 的样子了,吸取了之前的教训,出去上了个厕所,直接开写 T3 \texttt{T3} T3

想到一个 35   pts \texttt{35 pts} 35 pts 的朴素 dp \texttt{dp} dp,设 d p i , j dp_{i,j} dpi,j 表示 X X X 匹配到第 i i i 位, Y Y Y 匹配到第 j j j 位是否可行,所以就有转移 d p i , j = d p i − 1 , j ∣ d p i , j − 1 ∣ d p i − 1 , j − 1 dp_{i,j} = dp_{i - 1,j} | dp_{i,j - 1} | dp_{i - 1,j - 1} dpi,j=dpi1,jdpi,j1dpi1,j1。整一个想完写完大概 11:40 \texttt{11:40} 11:40,拍了大样例,能过,一阵狂喜,然后开最后一题。

按照赛前“没思路就写 dp \texttt{dp} dp”的策略,很快想出一个 36   pts \texttt{36 pts} 36 pts dp \texttt{dp} dp d p i , j dp_{i,j} dpi,j 表示到第 i i i 天时, ( j , i ) (j,i) (j,i) 区间均打卡而第 j − 1 j - 1 j1 天不打卡的最大能量。差不多 12:30 \texttt{12:30} 12:30,测大样例,突然发现有问题。一顿检查后发现是初始化的锅,修了以后所以大样例都能过。写完以后怕被卡常,在判断 ( j , i ) (j,i) (j,i) 区间的代码中利用 vector 加了一个二分,改完以后继续按原程序对拍,还真个我拍出错来了,发现还是初始化的问题,赶紧改!

12:45 \texttt{12:45} 12:45,不写了,开始检查文件名,路径,freopen 等等。

13:00 \texttt{13:00} 13:00,比赛结束,感觉还行,估分 100 + 40 + 25 + 36 = 211 100 + 40 + 25 + 36 = 211 100+40+25+36=211

后记

  • 这场比赛还是有一点点不满意。 T2 \texttt{T2} T2 应该是要写出来的,考场上想得太乱把自己绕进去了。 T4 \texttt{T4} T4 还有离散化的那一部分分没看见,这是可以拿到的;好像还有 10   pts \texttt{10 pts} 10 pts 的特殊部分也没看见……

  • 感谢 CCF \texttt{CCF} CCF 没有卡 T3 \texttt{T3} T3 的大常数做法(虽然能够通过读入时的特判解决这个问题)。以及 T2 \texttt{T2} T2 暴力不小心把 n n n 打成了 m m m,但由于暴力肯定是卡满的,所以出的数据全部都 n = m n = m n=m(属于是逃过一劫了)。

  • 出分啦,和自己估的一毛一样。感觉有点悬,祈祷初中生能去除的多一点。

  • 出分数线啦! 206 206 206!终于终于终于一等奖嘞!!!上体育课前同学来告诉我的,让我给激动得不得了。

  • 初高中的 OI \texttt{OI} OI 总算有了闭环,或许整个过程看上去很艰难,经历了停文化课,比赛失利等困难,但是我真的乐在其中。不论是洛谷的月赛,还是 CF \texttt{CF} CF 的深夜鏖战,总之努力没有白费!!!

  • 高中的竞赛算是结束了,但是洛谷的账号我是不会废滴,希望我在大学是能参加 ACM \texttt{ACM} ACM,然后继续开始写我的题解,赚我的咕值,提升我的排名!!!

  • 最后最后,纪念一下我比赛的四道题的赛时代码。

//T1 
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int MAX = 3e3 + 5;
const int MOD = 1e9 + 7;
inline int read ();
int n,m,mx[MAX],mn[MAX];char s[MAX][MAX];
int main ()
{
	n = read ();m = read ();
	for (int i = 1;i <= n;++i) mn[i] = INF;
	for (int i = 1;i <= n;++i) scanf ("%s",s[i] + 1);
	for (int i = 1;i <= n;++i)
		for (int j = 1;j <= m;++j)
			mx[i] = max (mx[i],s[i][j] - 'a'),mn[i] = min (mn[i],s[i][j] - 'a');
	for (int i = 1;i <= n;++i)
	{
		int ok = 1;
		for (int j = 1;j <= n;++j)
		{
			if (i == j) continue;
			if (mn[i] >= mx[j]) {ok = 0;break;}
		}
		if (ok) printf ("1");
		else printf ("0");
	}
	puts ("");
	return 0;
}
inline int read ()
{
	int s = 0,f = 1;
	char ch = getchar ();
	while (('0' > ch || ch > '9') && ch != EOF)
	{
		if (ch == '-') f = -1;
		ch = getchar ();
	}
	while ('0' <= ch && ch <= '9')
	{
		s = s * 10 + ch - '0';
		ch = getchar ();
	}
	return s * f;
}

//T2
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int MAX = 1e5 + 5;
const int MOD = 1e9 + 7;
inline int read ();
int ty,t,n,m,cnt,ans,vis[MAX],a[MAX],b[MAX],st[MAX];
//st[i] for i,the priority
char str[30][2];int x[30],y[30];
vector <pair <int,int> > ve[MAX];
void dfs (int u,int ti);
void solve (int x);
bool check ();
int main ()
{
//	freopen ("tribool.in","r",stdin);
//	freopen ("tribool.out","w",stdout);
	ty = read ();t = read ();
	if (ty <= 2)
	{
		while (t--)
		{
			n = read ();m = read ();ans = INF;
			for (int i = 1;i <= m;++i)
			{
				scanf ("%s",str[i]);x[i] = read ();
				if (str[i][0] == '+' || str[i][0] == '-') y[i] = read ();
			}
			solve (1);
			printf ("%d\n",ans);
		}
		return 0;
	}
	while (t--)
	{
		n = read ();m = read ();cnt = 0;
		for (int i = 1;i <= n;++i) a[i] = 0,st[i] = 0,ve[i].clear ();
		for (int i = 1;i <= m;++i)
		{
			char s[2];scanf ("%s",s);
			if (s[0] == '+')
			{
				int x = read (),y = read ();
				ve[y].push_back ({x,i});
				st[x] = i;
				for (int j = 1;j <= n;++j) vis[j] = 0;
				dfs (y,i);
			}
			else if (s[0] == '-')
			{
				int x = read (),y = read ();
			}
			else
			{
				int x = read ();
				if (s[0] == 'T') a[x] = 1;
				if (s[0] == 'F') a[x] = 2;
				if (s[0] == 'U') a[x] = 3;
				if (ty >= 5)
				{
					st[x] = i;
					for (int j = 1;j <= n;++j) vis[j] = 0;
					dfs (x,i);	
				}			
			}
		}
		for (int i = 1;i <= n;++i)
			if (a[i] == 3) ++cnt;
		printf ("%d\n",cnt);
	}
	return 0;
}
inline int read ()
{
	int s = 0,f = 1;
	char ch = getchar ();
	while (('0' > ch || ch > '9') && ch != EOF)
	{
		if (ch == '-') f = -1;
		ch = getchar ();
	}
	while ('0' <= ch && ch <= '9')
	{
		s = s * 10 + ch - '0';
		ch = getchar ();
	}
	return s * f;
}
void dfs (int u,int ti)
{
	vis[u] = 1;
	for (int i = 0;i < ve[u].size ();++i)
	{
		int v = ve[u][i].first;
		if (vis[v] || st[v] != ve[u][i].second) continue;
		a[v] = a[u];//st[v] = ti;
		dfs (v,ti);
	}
}
void solve (int x)
{
	if (x == n + 1)
	{
		if (check ())
		{
			int sum = 0;
			for (int i = 1;i <= n;++i) sum += (a[i] == 3);
			ans = min (ans,sum);
		}
		return ;
	}
	for (int i = 1;i <= 3;++i) a[x] = i,solve (x + 1);
}
bool check ()
{
	for (int i = 1;i <= n;++i) b[i] = a[i];
	for (int i = 1;i <= m;++i)
	{
		if (str[i][0] == '+') b[x[i]] = b[y[i]];
		else if (str[i][0] == '-')
		{
			if (b[y[i]] == 3) b[x[i]] = b[y[i]];
			else b[x[i]] = 3 - b[y[i]];
		}
		else
		{
			if (str[i][0] == 'F') b[x[i]] = 1;
			if (str[i][0] == 'T') b[x[i]] = 2;
			if (str[i][0] == 'U') b[x[i]] = 3;
		}
	}
	for (int i = 1;i <= n;++i)
		if (a[i] != b[i]) return 0;
	return 1;
}

//T3
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int MAX = 2e3 + 5;
const int MOD = 1e9 + 7;
inline int read ();
int ty,n,m,q,ans,a[MAX],b[MAX],c[MAX],d[MAX],dp[MAX][MAX];
bool check1 ();
bool check2 ();
int main ()
{
//	freopen ("expand.in","r",stdin);
//	freopen ("expand.out","w",stdout);
	ty = read ();n = read ();m = read ();q = read ();
	for (int i = 1;i <= n;++i) a[i] = read ();
	for (int i = 1;i <= m;++i) b[i] = read ();
	if (a[1] > b[1]) ans = check1 ();
	else  ans = check2 ();
	printf ("%d",ans);
	while (q--)
	{
		int dx = read (),dy = read ();
		for (int i = 1;i <= n;++i) c[i] = a[i];
		for (int i = 1;i <= m;++i) d[i] = b[i];
		while (dx--)
		{
			int x = read (),y = read ();
			a[x] = y;
		}
		while (dy--)
		{
			int x = read (),y = read ();
			b[x] = y;
		}
		if (a[1] > b[1]) ans = check1 ();
	    else  ans = check2 ();
		printf ("%d",ans);
		for (int i = 1;i <= n;++i) a[i] = c[i];
		for (int i = 1;i <= m;++i) b[i] = d[i];
	}
	puts ("");
	return 0;
}
inline int read ()
{
	int s = 0,f = 1;
	char ch = getchar ();
	while (('0' > ch || ch > '9') && ch != EOF)
	{
		if (ch == '-') f = -1;
		ch = getchar ();
	}
	while ('0' <= ch && ch <= '9')
	{
		s = s * 10 + ch - '0';
		ch = getchar ();
	}
	return s * f;
}
bool check1 ()
{
	for (int i = 1;i <= n;++i)	
		for (int j = 1;j <= m;++j) dp[i][j] = 0;
	dp[1][1] = (a[1] > b[1]);
	for (int i = 1;i <= n;++i)
	{
		for (int j = 1;j <= m;++j)
		{
			if (i == 1 && j == 1) continue;
			if (a[i] <= b[j]) continue;
			dp[i][j] |= dp[i][j - 1];
			dp[i][j] |= dp[i - 1][j - 1];
			dp[i][j] |= dp[i - 1][j];
		}
	}
	return dp[n][m];
}
bool check2 ()
{
	for (int i = 1;i <= n;++i)	
		for (int j = 1;j <= m;++j) dp[i][j] = 0;
	dp[1][1] = (a[1] < b[1]);
	for (int i = 1;i <= n;++i)
	{
		for (int j = 1;j <= m;++j)
		{
			if (i == 1 && j == 1) continue;
			if (a[i] >= b[j]) continue;
			dp[i][j] |= dp[i][j - 1];
			dp[i][j] |= dp[i - 1][j - 1];
			dp[i][j] |= dp[i - 1][j];
		}
	}
	return dp[n][m];
}

//T4
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int MAX = 1e3 + 5;
const int MOD = 1e9 + 7;
inline int read ();
struct node
{
	int ti;ll v;
} ;
int ty,t,n,m,k,d;
ll ans,dp[MAX][MAX];
vector <node> p[MAX];
vector <ll> sum[MAX];
bool cmp (node x,node y);
ll check (int x,int y);
int main ()
{
//	freopen ("run.in","r",stdin);
//	freopen ("run.out","w",stdout);
	ty = read ();t = read ();
	while (t--)
	{
		n = read ();m = read ();k = read ();d = read ();
		for (int i = 1;i <= n;++i)
			for (int j = 0;j <= min (n,k);++j) dp[i][j] = -INF;
		ans = -INF;
		for (int i = 1;i <= m;++i)
		{
			int x = read (),y = read (),v = read ();
			p[x].push_back ({x - y + 1,v});
		}
		for (int i = 1;i <= n;++i) sort (p[i].begin (),p[i].end (),cmp);
		for (int i = 1;i <= n;++i)
		{
			if (!p[i].size ()) continue;
			sum[i].push_back (p[i][0].v);
			for (int j = 1;j < p[i].size ();++j) sum[i].push_back (sum[i][j - 1] + p[i][j].v);
		}	
		dp[0][0] = 0;	
		for (int i = 1;i <= n;++i)
		{
			for (int j = 0;j <= min (i,k);++j)
			{
				int l = max (i - j + 1,1),r = i;
				dp[i][0] = max (dp[i][0],dp[i - 1][j]);
				if (j) dp[i][j] = max (dp[i][j],dp[i - 1][j - 1] + check (l,r) - d);
			}
		}
		for (int i = 0;i <= min (n,k);++i) ans = max (ans,dp[n][i]);
		printf ("%lld\n",ans);
		for (int i = 1;i <= n;++i) p[i].clear (),sum[i].clear ();
		for (int i = 1;i <= n;++i)
			for (int j = 0;j <= min (n,k);++j) dp[i][j] = -INF;
	}
	return 0;
}
inline int read ()
{
	int s = 0,f = 1;
	char ch = getchar ();
	while (('0' > ch || ch > '9') && ch != EOF)
	{
		if (ch == '-') f = -1;
		ch = getchar ();
	}
	while ('0' <= ch && ch <= '9')
	{
		s = s * 10 + ch - '0';
		ch = getchar ();
	}
	return s * f;
}
bool cmp (node x,node y)
{
	return x.ti < y.ti;
}
ll check (int x,int y)
{
	int l = 0,r = p[y].size () - 1,ans = -1;
	while (l <= r)
	{
		int mid = (l + r) >> 1;
		if (x <= p[y][mid].ti) ans = mid,r = mid - 1;
		else l = mid + 1;
	}
	if (ans == -1) return 0;
	if (ans == 0) return sum[y][sum[y].size () - 1];
	else return sum[y][sum[y].size () - 1] - sum[y][ans - 1];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值