首页 > 其他分享 >2023冲刺国赛模拟4

2023冲刺国赛模拟4

时间:2023-05-18 09:04:43浏览次数:46  
标签:long int 45 冲刺 add maxn 国赛 2023 now

A. xor on tree

操作分块,每 \(Q/B\) 次遍历整棵树,每个询问需要特殊查询 \(B\) 个

复杂度 \(\frac{Q}{B}nlog + QB\)

大力卡常能过

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int maxn = 1e5 + 5;
vector<int>son[maxn], point;
int n, w[maxn], q, qnt, ans[maxn], las[maxn];
int tim, dfn[maxn], dfnr[maxn], sum[maxn];
struct node{int tim, x, val;};
struct rem{int qid, tim;};
vector<node>o; vector<rem>qy[maxn]; 
bool in[maxn];
struct Trie{
	int ch[maxn * 31][2], si[maxn * 31], cnt = 1, rt = 1;
	void insert(int x, int op){
		int now = rt;
		for(int i = 30; i >= 0; --i){
			if(!ch[now][(x >> i) & 1])ch[now][(x >> i) & 1] = ++cnt;
			now = ch[now][(x >> i) & 1]; si[now] += op;
		}
	}
	int query(int x){
		int res = 0, now = 1;
		for(int i = 30; i >= 0 && now; --i){
			if(si[ch[now][((x >> i) & 1) ^ 1]])res += (1 << i), now = ch[now][((x >> i) & 1) ^ 1];
			else now = ch[now][(x >> i) & 1];
		}
		return res;
	}
}T;
void pre(int x){
	dfn[x] = ++tim;
	for(int v : son[x])pre(v);
	dfnr[x] = tim;
}
void dfs(int x){
	if(sum[dfn[x] - 1] == sum[dfnr[x]])return;
	if(!in[x])T.insert(w[x], 1);
	for(rem v : qy[x])ans[v.qid] = T.query(v.tim);
	for(int v : son[x])dfs(v);
	if(!in[x])T.insert(w[x], -1);
}
void sol(){
	for(int i = 1; i <= n; ++i)sum[i] += sum[i - 1];
	dfs(1);
	for(node v : o)
		if(v.tim){
			for(int p : point)
				if(dfn[v.x] >= dfn[p] && dfnr[v.x] <= dfnr[p])
					ans[v.val] = max(ans[v.val], w[v.x] ^ w[p]);
		}else w[v.x] = v.val;
	o.clear(); point.clear(); for(int i = 1; i <= n; ++i)sum[i] = in[i] = false, qy[i].clear();
}
int main(){
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	n = read(), q = read();
	for(int i = 1; i <= n; ++i)las[i] = w[i] = read();
	for(int i = 2; i <= n; ++i)son[read()].push_back(i);
	pre(1);
	int B = sqrt(n * 30) * 3.4;
	for(int i = 1; i <= q; ++i){
		int op = read(), u = read();
		if(!op){o.push_back({0, u, read()}); in[u] = true; las[u] = o.back().val; point.push_back(u); }
		else {qy[u].push_back({++qnt, las[u]}); o.push_back({1, u, qnt}); ++sum[dfn[u]];}
		if(i % B == 0)sol();
	}
	sol();
	for(int i = 1; i <= qnt; ++i)printf("%d\n",ans[i]);
	return 0;
}

B. calc on lowbit

转成差分的形式,现在计算\(\sum_{i = 1}^r f(i)\)

设 \(f, g _{i, 1 / 0, 1 / 0}\) 表示考虑后 \(i\) 位,是否有进位,是否比 \(r\) 大的概率和期望

枚举该位填啥进行转移

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

ll read(){
	ll x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
const int mod = 998244353, inv2 = (mod + 1) >> 1;

int f[62][2][2], g[62][2][2];
void add(int &x, int y){x += y; if(x >= mod)x -= mod;}
int calc(ll r){
	memset(f, 0, sizeof(f));
	memset(g, 0, sizeof(g));
	g[0][0][0] = 1;
	for(int i = 0; i < 60; ++i){
		for(int j = 0; j <= 1; ++j)
			for(int k = 0; k <= 1; ++k)
				for(int p = 0; p <= 1; ++p){
					bool big = ((r >> i) & 1) < p || (((r >> i) & 1) == p && k); 
					if(j + p == 0){
						add(f[i + 1][0][big], f[i][j][k]);
						add(g[i + 1][0][big], g[i][j][k]);
					}else if(j + p == 1){
						int val = 1ll * (f[i][j][k] + g[i][j][k]) * inv2 % mod;
						int v2 = 1ll * g[i][j][k] * inv2 % mod;
						add(f[i + 1][0][big], val);
						add(g[i + 1][0][big], v2);
						add(f[i + 1][1][big], val);
						add(g[i + 1][1][big], v2);
					}else{
						add(f[i + 1][1][big], f[i][j][k]);
						add(g[i + 1][1][big], g[i][j][k]);
					}
				}
	}
	return (0ll + f[60][0][0] + f[60][1][0] + 2ll * g[60][1][0]) % mod;
}
int main(){
	freopen("calc.in","r",stdin);
	freopen("calc.out","w",stdout);
	int T = read();
	for(int i = 1; i <= T; ++i){
		ll l = read(), r = read();
		printf("%d\n",(calc(r) - calc(l - 1) + mod) % mod);
	}
	return 0;
}

C. color on board

数据范围就很网络流

每个点建出四个点,表示横着涂黑,竖着涂白,没有竖着涂黑,没有横着涂白

对于 \(ak + b\) 的 \(b\), 钦定在最后的位置贡献

以横黑为例,如果 \((i,j)\) 涂了, \((i + 1, j)\) 没涂,那么需要有 \(b\) 的代价

或者其是最后一列,涂白的代价本身就是 \(a + b\)

其他情况同理

现在考虑单个点的限制

如果最终要涂黑,那么之前不能涂白,改白色的代价为 \(inf\), 如果没有横竖涂黑,那么需要单点涂黑,有 \(c\) 的代价

建出来长这样

image

对于白色,可以证明一定不会被同方向不同颜色涂,所以涂横黑必然涂竖白或者单点涂白

并且限制了不能两次涂黑

image

code
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int read(){
	int x = 0; char c = getchar();
	while(!isdigit(c))c = getchar();
	do{x = x * 10 + (c ^ 48); c = getchar();}while(isdigit(c));
	return x;
}
typedef long long ll;

const int inf = 0x3f3f3f3f;
const int maxn = 41 * 41 * 5;
const int maxm = maxn * 200;
int n, m, a, b, c;
char mp[45][45];
int hh[45][45], sb[45][45], fsh[45][45], fhb[45][45], cnt;
struct Dinic{
	int s, t, head[maxn], tot = 1;
	struct edge{int to, net, val;}e[maxm];
	void add(int u, int v, int w){
		e[++tot].net = head[u];
		head[u] = tot;
		e[tot].to = v;
		e[tot].val = w;
	}
	void link(int u, int v, int w){add(u, v, w); add(v, u, 0);}
	int dep[maxn], now[maxn];
	bool bfs(){
		for(int i = 1; i <= t; ++i)dep[i] = 0;
		queue<int>q; dep[s] = 1; q.push(s);
		now[s] = head[s];
		while(!q.empty()){
			int x = q.front(); q.pop();
			for(int i = head[x]; i; i = e[i].net){
				int v = e[i].to;
				if(e[i].val > 0 && dep[v] == 0){
					dep[v] = dep[x] + 1;
					now[v] = head[v];
					if(v == t)return true;
					q.push(v);
				}
			}
		}
		return false;
	}
	int dfs(int x, int from){
		if(x == t || from <= 0)return from;
		int res = from, i;
		for(i = now[x]; i; i = e[i].net){
			int v = e[i].to;
			if(e[i].val > 0 && dep[v] == dep[x] + 1){
				int k = dfs(v, min(res, e[i].val));
				if(k <= 0)dep[v] = 0;
				e[i].val -= k;
				e[i ^ 1].val += k;
				res -= k;
				if(res <= 0)break;
			}
		}
		now[x] = i;
		return from - res;
	}
	int dinic(){
		int ans = 0;
		while(bfs())ans += dfs(s, inf);
		return ans;
	}
	void clear(){
		for(int i = 1; i <= t; ++i)head[i] = 0;
		cnt = 0; tot = 1;
	}
	void init(){
		n = read(), m = read(), a = read(), b = read(), c = read();
		for(int i = 1; i <= n; ++i)scanf("%s",mp[i] + 1);
		for(int i = 1; i <= n; ++i)for(int j = 1; j <= m; ++j)hh[i][j] = ++cnt, sb[i][j] = ++cnt, fsh[i][j] = ++cnt, fhb[i][j] = ++cnt;
		s = ++cnt, t = ++cnt;
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j < m; ++j){
				link(hh[i][j + 1], hh[i][j], b);
				link(fhb[i][j], fhb[i][j + 1], b);
			}
		for(int i = 1; i < n; ++i)
			for(int j = 1; j <= m; ++j){
				link(sb[i + 1][j], sb[i][j], b);
				link(fsh[i][j], fsh[i + 1][j], b);
			}
		for(int i = 1; i <= n; ++i)
			for(int j = 1; j <= m; ++j)
				if(mp[i][j] == '#'){
					link(hh[i][j], fsh[i][j], c);
					link(s, sb[i][j], inf);
					link(s, hh[i][j], a + (j == m ? b : 0));
					link(fhb[i][j], t, inf);
					link(fsh[i][j], t, a + (i == n ? b : 0));
				}else{
					link(s, hh[i][j], a + (j == m ? b : 0));
					link(s, sb[i][j], a + (i == n ? b : 0));
					link(fsh[i][j], t, a + (i == n ? b : 0));
					link(fhb[i][j], t, a + (j == m ? b : 0));
					link(sb[i][j], hh[i][j], c);
					link(fsh[i][j], fhb[i][j], c);
					link(fsh[i][j], hh[i][j], inf);
				}
		printf("%d\n", dinic());
		clear();
	}
}w;
int main(){
	freopen("color.in","r",stdin);
	freopen("color.out","w",stdout);
	int T = read();
	for(int i = 1; i <= T; ++i)w.init();
	return 0;
}

标签:long,int,45,冲刺,add,maxn,国赛,2023,now
From: https://www.cnblogs.com/Chencgy/p/17410835.html

相关文章

  • 【补题】2023河南省赛
    题目链接https://codeforces.com/gym/104354A.小水獭游河南签到题。初看有点吓人,跟回文串有关,会不会是PAM啥的,然后是大水题。。。容易发现A串的约束非常强,没有重复字符,意味着A串的长度最大也就是26。我们枚举A串,同时看剩余的后缀是不是回文串就行了。时间复杂度\(\Theta(26......
  • 2023.5.17
    1题目描述:定义一个时间类,小时和分钟是其两个私有成员数据。输入一个起始时间和一个结束时间(起始时间早于结束时间),通过运算符重载-(减号),计算这两个时间相隔多少分钟。说明:这两个时间在同一天之内,且采用24小时计时分式,即从00:00-23:59。23输入格式:测试输入包含若干......
  • 【愚公系列】2023年05月 .NET CORE工具案例-对象映射Master的使用
    (文章目录)前言对象映射框架Master可以帮助开发人员将对象映射到数据库,以进行数据持久化。它还可以支持ORM(对象关系映射),以及其他数据库技术,比如存储过程。它可以帮助开发人员更快、更有效地完成数据库操作。Master官网:https://github.com/MapsterMapper/Mapster一、对象映射m......
  • 2023-05-17:一个正整数如果能被 a 或 b 整除,那么它是神奇的。 给定三个整数 n , a , b
    2023-05-17:一个正整数如果能被a或b整除,那么它是神奇的。给定三个整数n,a,b,返回第n个神奇的数字。因为答案可能很大,所以返回答案对10^9+7取模后的值。输入:n=4,a=2,b=3。输出:6。答案2023-05-17:过程描述:1.计算a和b的最小公倍数lcm。2.初始化......
  • 考研学习 | 每日回顾(2023年5月15日)
    昨天的考研数学笔记常用的极限两原则:拆分之后的所有式子都要有极限且只能在乘除法之间使用等价无穷小替换如果一个部分无法直接被化简计算,就尝试整体代换反三角函数arcsinx和arccosx的关系遇到三角函数问题时要知道:不同的三角函数之间可以相互转换......
  • 2023-05-17 刷题
    算法题目1:【Mid】47.全排列II思路分析:将原问题转换成子问题,先不考虑重复元素,例如P{1,2,3}={"1"+P{2,3},"2"+P{1,3},"3"+P{1,2}}。之后再考虑重复元素。怎么枚举?枚举每个位置可以填哪些数。【这种枚举方式能保证字典序,除此外,还有一种,枚举每个数可以放到哪个位置上,......
  • 考研学习 | 每日回顾(2023年5月17日)
    昨天的考研数学笔记求解偏导数的时候一定要清楚当前谁是自变量:文内有小技巧求偏导时,函数的第一部分变量用1表示,第二部分变量用2表示......
  • 考研学习 | 每日回顾(2023年5月13日)
    昨天的考研数学笔记只对x求偏导时,y的值可以提前代入y不一定就是x的函数......
  • 2023 湖北ccpc
    F.InverseManacher题意:给定回文半径数组,构造回文串(只包含a,b)分析:题目保证一定合法,我们考虑每个'|'位置上的回文半径如果r=1:说明前一个位置与后一个位置上的字符不同如果r>1:说明前一段位置与后一段位置回文,则要保证前后位置上的字符相同实现:#include<bits/std......
  • YACS 2023年5月月赛 甲组 T1 子集和(六) 题解
    YACS老师说这是道分治,但就不告诉我怎么做,我硬是用线段树卡了过去...特别解气的是把AC图片发了过去(我就是在YACS上的编程课)莫队好了说点正经的,看到是谁谁谁的倍数就能想到DP,状态设计也很水啦!设f[i]为当前考虑到的区间内,子集和%k=i的数量。新加入一个元素时,循环0~......