首页 > 其他分享 >CF1710 题解

CF1710 题解

时间:2023-10-23 22:11:30浏览次数:34  
标签:return int 题解 ll tot leq oplus CF1710

CF1710 题解

A

看图写话

想象一个格子以及周围同色格的颜色必须呈一个三叉的形状:

#           #            #
##         ##           ###         ###
#           #                        #

这些三叉拼起来最小的形状,就是两个以上的整行,或整列。所以遍历每一种颜色,通过整除观察它最多能填几列,如果 \(1\) 列就不能放,如果奇数列就要看是否一个数可以取到奇数;再对行做一遍即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
typedef long long ll;
ll a[N],n,m,k;
inline bool try_line()
{
	ll tmp = 0; int can_be_odd = 0;
	for(int i = 1;i <= k;i++)
	{
		if(a[i] / m <= 1) continue;
		if(a[i] / m > 2) can_be_odd = 1;
		tmp += a[i] / m;
	}
	return tmp >= n && ((n & 1) ? can_be_odd : 1);
}
inline bool try_column()
{
	ll tmp = 0; int can_be_odd = 0;
	for(int i = 1;i <= k;i++)
	{
		if(a[i] / n <= 1) continue;
		if(a[i] / n > 2) can_be_odd = 1;
		tmp += a[i] / n;
	}
	return tmp >= m && ((m & 1) ? can_be_odd : 1);
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m>>k;
		for(int i = 1;i <= k;i++) cin>>a[i];
		if(try_line()) puts("Yes");
		else if(try_column()) puts("Yes");
		else puts("No");
	}
	return 0;
}

B

Rairn 没来qwq

场上没切这题,耻辱。

考虑答案要算总共贡献减去一个凸函数的值是否超过 \(m\) 。考虑最后结果是很多的 “山峰”,只有这些 “峰顶” 有可能成为删掉过后的最大值,然而这些 “山峰”有斜率转折且是邻域内的极大值,所以一定是凸函数顶点 \(x_i\) 。

所以我们只需要计算所有降雨时这 \(n\) 个顶点的函数值,直接动态开点线段树将 \(k,b\) 塞进去即可(可以离散化)。算出来后挑出那些大于 \(m\) 的函数值,扫描每个 \(i\) :

如果对于一个大于 \(m\) 的 \(j\) ,\(i\) 没有包含 \(j\) ,那么 \(j\) 一定会成为剩下大于 \(m\) 的那一个,不合法,不然减去 \(i\) 的贡献后 ,\(j\) 处的值(称作 \(v_j\)),需要小于 \(m\) ,列出式子:

\[v_j - (p_i - |x_i - x_j|) \leq m \]

拆为:

\[v_j - (p_i - x_i + x_j) \leq m\\ v_j - (p_i + x_i - x_j) \leq m \]

移项:

\[v_j - x_j \leq m + x_i - p_i\\ v_j + x_j \leq m - p_i - x_i \]

所以要满足对于所有 \(j\) ,都有这个式子,直接将最大的 \(v_j - x_j,v_j + x_j\) 求出来 \(\Theta(1)\) 判断即可,复杂度 \(\Theta (n \log n)\) 。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5,TOP = 1e9;
typedef long long ll;
bool st;
ll q[N];
int cnt = 0,n,m,x[N],p[N],ans[N];
struct SegTree{
	ll k[N * 50],b[N * 50];
	int lc[N * 50],rc[N * 50],tot;
	inline int nn()
	{
		++tot;
		k[tot] = 0; b[tot] = 0; lc[tot] = 0; rc[tot] = 0;
		return tot;
	} 
	inline void modify(ll l,ll r,ll L,ll R,ll nk,ll nb,int pos)
	{
		if(L <= l && r <= R) {k[pos] += nk; b[pos] += nb; return;}
		ll mid = (l + r) >> 1;
		if(L <= mid) {if(!lc[pos]) lc[pos] = nn(); modify(l,mid,L,R,nk,nb,lc[pos]);}
		if(R > mid) {if(!rc[pos]) rc[pos] = nn(); modify(mid + 1,r,L,R,nk,nb,rc[pos]);}
	}
	inline ll query(ll l,ll r,ll x,ll nk,ll nb,int pos)
	{
		nk += k[pos]; nb += b[pos];
		if(l == r) {return nk * x + nb;}
		ll mid = (l + r) >> 1;
		if(x <= mid) return query(l,mid,x,nk,nb,lc[pos]);
		else return query(mid + 1,r,x,nk,nb,rc[pos]);
	} 
}t;
bool ed;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		t.tot = 0; cnt = 0; t.nn();
		for(int i = 1;i <= n;i++) 
		{
			cin>>x[i]>>p[i];
			t.modify(-TOP,TOP,x[i] - p[i],x[i],1,p[i] - x[i],1);
			t.modify(-TOP,TOP,x[i] + 1,x[i] + p[i],-1,x[i] + p[i],1);
		}
		for(int i = 1;i <= n;i++) q[i] = t.query(-TOP,TOP,x[i],0,0,1);
		ll maxid = -1e18,maxia = -1e18;
		for(int i = 1;i <= n;i++) if(q[i] > m) maxia = max(maxia,q[i] + x[i]),maxid = max(maxid,q[i] - x[i]);
		for(int i = 1;i <= n;i++)
		{
			if(1ll * p[i] - x[i] + m >= maxid && 1ll * p[i] + x[i] + m >= maxia) ans[i] = 1;
			else ans[i] = 0;
		} 
		for(int i = 1;i <= n;i++) cout<<ans[i];
		cout<< '\n';
	}
	return 0;
}

C

考虑每一位去做,就是数位 dp。本来想枚举 \(a \oplus b\) 和 \(a \oplus c\) 的值,但是考虑不好算 \(a,b,c \leq n\) 的范围,所以转而枚举 \(a,b,c\) 的值。

钦定 \(a \oplus b,b \oplus c \leq a \oplus c\),将当前位选择列出可得:

value a b c
0 0 0 0
1 0 0 1
2 0 1 0
3 0 1 1
4 1 0 0
5 1 0 1
6 1 1 0
7 1 1 1

由于前两个异或小于等于第三个,所以容易想到设两个状态 \(ls1,ls2\) 表示根据前 \(siz\) 位后是否已经有 \(a \oplus b \leq a \oplus c\) , \(b \oplus c \leq a \oplus c\) 。容易发现如果没有则不能选 \(2,5\) 状态。

我们知道两个异或值相加一定大于等于另外一个异或值(因为两个异或值异或起来等于第三个,而且 \(x \oplus y \leq x + y\)),不取等的条件是两个要有交,所以再记一个状态 \(eq\) 表示是否存在一个位 \(i\) ,使得 \((a \oplus b)_i = (b \oplus c)_i\) 。

最后记三个 \(li1,li2,li3\) 代表 \(a,b,c\) 是否顶上限即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5,MOD = 998244353;
int a[N],n;
typedef long long ll;
ll f[N][8][8];
inline int zip(int x,int y,int z) {return x | (y << 1) | (z << 2);}
inline ll dfs(int siz,bool ls1,bool ls2,bool eq,bool li1,bool li2,bool li3)
{
	if(siz == n + 1) {return eq;}
	if(f[siz][zip(ls1,ls2,eq)][zip(li1,li2,li3)] != -1) return f[siz][zip(ls1,ls2,eq)][zip(li1,li2,li3)];
	int top1 = (li1 ? a[siz] : 1),top2 = (li2 ? a[siz] : 1),top3 = (li3 ? a[siz] : 1);
	ll res = 0;
	for(int i = 0;i <= top1;i++)
		for(int j = 0;j <= top2;j++)
			for(int k = 0;k <= top3;k++)
			{
				if(!ls1 && (i ^ j) > (i ^ k)) continue;
				if(!ls2 && (j ^ k) > (i ^ k)) continue;
				res += dfs(siz + 1,ls1 | ((i ^ j) < (i ^ k)),ls2 | ((j ^ k) < (i ^ k)),eq | (((i ^ j) == 1) && ((j ^ k) == 1)),li1 & (i == a[siz]),li2 && (j == a[siz]),li3 && (k == a[siz]));
				res %= MOD; 
			}
	return f[siz][zip(ls1,ls2,eq)][zip(li1,li2,li3)] = res;
}
char s[N];
int main()
{
	memset(f,-1,sizeof(f));
	scanf("%s",s + 1);
	n = strlen(s + 1); 
	for(int i = 1;i <= n;i++) a[i] = s[i] - '0';
	cout<<dfs(1,0,0,0,1,1,1) * 3 % MOD;
	return 0;
}

标签:return,int,题解,ll,tot,leq,oplus,CF1710
From: https://www.cnblogs.com/TheLastCandy/p/17783613.html

相关文章

  • CSP-S 2023 游记 & 总结 & 题解
    游记到了机房发现是Windows10,感觉不错。比赛开始果断启动虚拟机,怎么今年PDF密码这么复杂啊,我记得去年挺简单的来着,好像是believe2022?看了一遍题,有理由怀疑T1是J的题,但是一开始读错了,以为只能转一下,后来计算转动幅度的时候忘记对\(10\)取模,怒调1h。T2一开始以为是容......
  • 【题解】CF1710 合集
    CF1710AColorthePicture标签:思维题\(C^-\)典型的有图有真相,嘻嘻(抽风了?显然有一个结论,我们颜色要么一行一行天,要么一列一列填。并且填进去的颜色必须不少于两行/列然后就是记一个ans和一个over表示如果每个颜色都两行/列填进去能填的最多列数,以及两行/列填进去后还能......
  • Educational Codeforces Round 144(CF1796 D~E) 题解
    D.MaximumSubarray题目链接十分钟秒了一道*2000,非常爽,但是个人感觉确实非常简单。下面令\(b_i=a_{i}-x\),\(b_i'=a_i+x\)。因为\(k<=20\),因此考虑一个复杂度与\(k\)相关的做法。不妨dp:设\(f_{i,j,0/1}\)表示考虑了前\(i\)个数,对\(j\)个数加上了\(x\),第\(i\)......
  • CF1893E题解
    分析第一眼:博弈论。第二眼:呃……贪心?实际:DP。首先想这个游戏大抵存在必胜策略,否则不会让我们求。思考先手必胜条件,就是如何让这个数组最后只剩下一个数。设数列之和为\(sum\)。发现每次操作给两个数减的数字是一样的。那么对于每次操作,\(\Deltasum\)都为两者之间更少的......
  • CSP-S 2023 种树-题解
    CSP-S2023种树-题解闲话Mark.Down看错题面了,我一直以为树是倒着长的。题目描述给定一棵树,每天可以选择一个与已种树的地块相连的地块种树,每棵树每天会长\(max(1,c_i\timesx+b_i)\)米(\(x\)代表从任务开始第一天的天数),问最少多少天可以使\(\foralli\inn,Height_i\gea_i\)......
  • P8820(csp-s 2022 T4)题解
    背景:由于FZ考试因疫情取消,于是我们学校组织了线上测试。赛场连假做法都没打完,然后暴力忘记交了。。。题目链接参考博客题目评价:场切有点困难,但是76分比较容易。解法一眼\(ddp\),没话说。下面假设树以\(1\)为根。一次传输称作从一个点跳到另一个点。设询问的两个点为\(......
  • 题解合集
    CF1846:CF1846ACF1846BCF1846CCF1846DCF1846E......
  • CF1839D题解
    分析啊这道题就做得很难受了……手玩一下样例,不难发现答案就是分出\(k\)段不是单调上升序列的序列,求这些序列的最小长度和。显然有状态\(f_{l,r,k}\)表示\([l,r]\)序列分成\(k\)段的最小长度和。转移很好想,即枚举\(x\),\(y\)分别表示左区间的右端点以及段数,空间复杂度\(\math......
  • 题解:【CF1888E】 Time Travel
    题目链接刚从modinte那里学到的广义dijkstra。注意到一定不会有路径形如\(x\toy\tox\),这样等价于\(x\)在原地等上两个时刻,我们记\(d_i\)表示到达\(i\)节点需要的最少时间。建图,边权为当前这一条边在哪一个历史时刻。然后用一个set来存下每个历史时刻在第几次时间......
  • CSP-S 2023 消消乐-题解
    CSP-S2023消消乐-题解闲话省流:longlong模拟pair好抽象的题,可惜考场上没做出来。感觉其实是一个挺有趣的题的。题目描述小L现在在玩一个低配版本的消消乐,该版本的游戏是一维的,一次也只能消除两个相邻的元素。现在,他有一个长度为\(n\)且仅由小写字母构成的字符串。我......