CF 1749 题解

比赛链接:https://codeforces.com/contest/1749

题解:
AB
水题

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

int r[15],c[15];

void solve(){
	int n,m;scanf("%d%d",&n,&m);
	memset(r,0,sizeof r);memset(c,0,sizeof c);
	for(int i=1;i<=m;i++){
		int x,y;scanf("%d%d",&x,&y);
		r[x] = c[y] = 1;
	}
	int fg = 0;
	for(int i=1;i<=n;i++)
		fg |= r[i] == 0,
		fg |= c[i] == 0;
	if(fg)puts("YES");
	else puts("NO");
}

signed main(){
	int te;scanf("%d",&te);
	while(te--)solve();

	return 0;
}
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

signed main(){
	int te;scanf("%d",&te);
	while(te--){
		int n;scanf("%d",&n);
		LL sum=0,mx=-1e18;;
		for(int i=1,x;i<=n;i++)scanf("%d",&x),sum+=x;
		for(int i=1,x;i<=n;i++)scanf("%d",&x),sum+=x,mx=max(mx,1ll*x);
		printf("%I64d\n",sum-mx);
	}

	return 0;
}

C
Bob肯定优先取小的,Alice优先取大的。枚举k暴力模拟这个过程即可

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f;

void solve(){
	int n;scanf("%d",&n);
	int a[105];
	int bin[105],ain[105];memset(bin,0,sizeof bin);memset(ain,0,sizeof ain);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),++bin[a[i]],++ain[a[i]];
	for(int i=2;i<=100;i++)ain[i]+=ain[i-1];
	int bbin[105],aain[105];
	memcpy(bbin,bin,sizeof bbin);memcpy(aain,ain,sizeof aain);
	int qz = 0;
	for(int k=100;k>=1;k--){
		memcpy(bin,bbin,sizeof bin);memcpy(ain,aain,sizeof ain);
		int gg=0;qz=0;
		for(int i=k;i>=1;i--){
			if(ain[i] - qz <= 0){
				gg=1;break;
			}
			if(bin[i] == 0)
				for(int j=i;j>=1;j--)
					if(bin[j]){--bin[j];--ain[j];break;}
					else -- ain[j];
			++ qz;
		}
		if(!gg){printf("%d\n",k);return ;}
	}
	puts("0");
}

signed main(){
	int te;scanf("%d",&te);
	while(te --)solve();

	return 0;
}

D
[1..1]显然是一组解,考虑能不能有其它解
考虑容斥,什么情况下无解?对于所有的a[i],所有的\(1\leq j \leq i\),都有\(gcd(a[i],j) \neq 1\)
显然只需要考虑素因子即可,也即是1~i的所有素数即可
从1~n,如果当前i为素数,那么\(cds = cds \times i\),当前这一位出现不合法序列的次数是i/cds,然后 tmp = tmp * i/cds,tmp表示的就是长度为 i 的所有不合法序列的个数,对于所有的i计算一下即可
总共的情况是什么呢?因为每一位可以任意取,就是m+m*m+...+pw(m,n)
容斥一下即可
需要快速乘

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 3e5 + 5, mod=998244353;

int notpm[maxn], pm[maxn], pcnt=0;

void xxs(){
	notpm[1] = 1;
	for(int i=2;i<=300000;i++){
		if(!notpm[i]){
			pm[++ pcnt] = i;
		}
		for(int j=1;j<=pcnt && i * pm[j] <= 300000; j++){
			notpm[i*pm[j]] = 1;
			if(i%pm[j] == 0)break;
		}
	}
}

int n;
LL m;
LL bs = 1, nbs = 1;
int gg = 0;
int tmp =1 ;
inline LL ksc(LL x,LL y,LL p){
	LL z=(long double)x/p*y;
	LL res=(ULL)x*y-(ULL)z*p;
	return (res+p)%p;
}
signed main(){
	scanf("%d%I64d",&n,&m);
	xxs();
	int pi = 1;
	LL ans = 0;
	for(int i=1;i<=n;i++){
		bs = ksc(bs, m, mod);
//		bs = 1ll * bs * m % mod;
		if(pm[pi] == i && !gg){
			nbs = 1ll * nbs * pm[pi];
			if(nbs > m){
				gg = 1;
			}
			++ pi;
		}
		(ans += bs) %= mod;
		if(!gg){
			tmp = ksc(tmp, m/nbs, mod);
//			tmp = 1ll * tmp * (m/nbs) % mod;
			(ans += mod - tmp) %= mod;
		}
//		cout << nbs << " "<< bs << " " << gg << '\n';
	}
	printf("%I64d\n",ans);

	return 0;
}

E
我的01bfs博客中有这个题

F
考虑简化版:对每个点子树中距离这个点为d(0~20)的所有点进行修改,查找点权?
显然直接对这个点修改,查询的时候对于所有的0~20的树,求ans0[fa[x]] + ans1[fa[fa[x]]] + ... 即可
回到这个题,(u,v)路径,设lca为lc
可以拆成这3个路径:[u,lc) (lc,v] lc及fa[lc],...
[u,lc):按照简化版的处理,对于ansd[u]+k, ansd[fa[u]]+k, ... ansd[son[lc]]+k,表示对于u的子树中距离u为d的点权都+k,...
注意这里会存在son[lc]子树中距离son[lc]距离<d的点没有处理,但是这块能被包含在lc fa[lc] ... 中,此处不在赘述
[v,lc):同理
lc fa[lc] .. : 手玩一下发现ansd[lc]+k ans(d-1)[lc]+k ans(d-1)[fa[lc]]+k ans(d-2)[fa[lc]]+k ... 可以涵盖所有情况。注意如果到根了,需要把d d-1 d-2.. 0都给加上
因此我们需要实现的是:树上链加、单点加、单点查询
树剖解决,也可以树状数组
时间复杂度O(qdlogn)

// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>

using namespace std;

typedef long long LL;

const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 2e5+5;

int n;
vector<int>g[maxn];
int a[maxn];
int dfn[maxn], seq[maxn], dfs_clock;
int dep[maxn], heavy[maxn], top[maxn], sz[maxn], fa[maxn];
struct seg{
	int sum,lazy;
}se[maxn << 2][23];

void dfs1(int x,int fat){
	fa[x] = fat;
	sz[x] = 1;
	dep[x] = dep[fat] + 1;
	
	for(int u : g[x]){
		if(u == fat)continue;
		dfs1(u, x);
		sz[x] += sz[u];
		if(!heavy[x] || sz[u] > sz[heavy[x]])
			heavy[x] = u;
	}
}

void dfs2(int x,int now){
	top[x] = now;
	dfn[x] = ++ dfs_clock;
	seq[dfs_clock] = x;
	
	if(!heavy[x])return ;
	dfs2(heavy[x], now);
	for(int u : g[x]){
		if(u == heavy[x] || u == fa[x])continue;
		dfs2(u,u);
	}
}

void build(int x,int y,int num){
	for(int i=0;i<=20;i++)se[num][i].sum = se[num][i].lazy = 0;
	if(x == y){
		return ;
	}
	int mid = x + y >> 1;
	build(x,mid,num << 1);build(mid+1, y, num<<1 | 1);
}

void pushdown(int l,int r,int num,int d){
	if(!se[num][d].lazy)return ;
	int mid = l+r>>1;
	(se[num << 1][d].sum += 1ll*(mid-l+1)*se[num][d].lazy);
	(se[num << 1|1][d].sum += 1ll * (r-mid)*se[num][d].lazy);
	se[num << 1][d].lazy += se[num][d].lazy;
	se[num << 1|1][d].lazy += se[num][d].lazy; 
	se[num][d].lazy = 0;
}

int getlca(int x,int y){
	int tx = top[x], ty = top[y];
	while(tx != ty){
		if(dep[tx] < dep[ty])swap(x, y), swap(tx, ty);
		x = fa[tx], tx = top[x];
	}
	if(dep[x] > dep[y])return y;
	return x;
}

void update(int x,int y,int k,int l,int r,int num,int d){
	if(x <= l && r <= y){
		(se[num][d].sum += 1ll * (r-l+1) * k);
		se[num][d].lazy += k;
		return ;
	}
	pushdown(l,r,num,d);
	int mid = l+r >> 1;
	if(y <= mid)update(x,y,k,l,mid,num<<1,d);
	else if(x > mid)update(x,y,k,mid+1,r,num<<1|1,d);
	else update(x,y,k,l,mid,num<<1,d), update(x,y,k,mid+1,r,num<<1|1,d);
	se[num][d].sum = (se[num<<1][d].sum + se[num<<1|1][d].sum);
}

void upd(int to,int k,int l,int r,int num,int d){
	if(l == r){
		se[num][d].sum += k;
		return ;
	}
	pushdown(l,r,num,d);
	int mid = l+r>>1;
	if(to<=mid)upd(to,k,l,mid,num<<1,d);
	else upd(to,k,mid+1,r,num<<1|1,d);
	se[num][d].sum = se[num << 1][d].sum + se[num<<1|1][d].sum; 
}

void access(int x,int k,int d){
	int curd = d;
	while(1){
		upd(dfn[x],k,1,n,1,curd);
		if(curd == 0)break;
		upd(dfn[x],k,1,n,1,--curd);
		
		if(x == 1)break;
		x = fa[x];
	}
	while(curd >= 1)upd(dfn[1],k,1,n,1,--curd);
}

int query(int to,int l,int r,int num,int d){
	if(l == r)return se[num][d].sum;
	int mid = l+r>>1;
	pushdown(l,r,num,d);
	if(to <= mid)return query(to,l,mid,num<<1,d);
	else return query(to,mid+1,r,num<<1|1,d);
}

void chain_add(int x,int y,int k,int d){
//	printf("(%d,%d)\n",x,y);
	int tx = top[x], ty = top[y];
	while(tx != ty){
		if(dep[tx] < dep[ty])swap(x, y), swap(tx, ty);
		update(dfn[tx], dfn[x], k, 1, n ,1, d);
		x = fa[tx], tx = top[x]; 
	}
	if(dep[x] > dep[y])swap(x, y);
	update(dfn[x], dfn[y], k, 1, n, 1, d);
}

signed main(){
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++){
		int x,y;scanf("%d%d",&x,&y);
		g[x].push_back(y), g[y].push_back(x);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,n,1);
	
	int m;scanf("%d",&m);
	while(m --){
		int op;scanf("%d",&op);
		if(op == 1){
			int x;scanf("%d",&x);
			int curx = x;
			int ans = 0;
			for(int d = 0;d<=20;d++){
				ans += query(dfn[curx],1,n,1,d);
				if(curx == 1)break;
				curx = fa[curx];
			}
			printf("%d\n",ans);
		}
		if(op == 2){
			int u,v,k,d;scanf("%d%d%d%d",&u,&v,&k,&d);
			int lc = getlca(u, v);
//			printf("?? %d\n",lc);
			if(lc == u || lc == v){
				int tx = lc == u ? v : u;
				int ty = lc;
				chain_add(tx,ty,k,d);
				upd(dfn[lc],-k,1,n,1,d);
				access(lc, k, d); 
			}else{
				chain_add(u,lc,k,d);
				upd(dfn[lc],-k,1,n,1,d);
				chain_add(v,lc,k,d);
				upd(dfn[lc],-k,1,n,1,d);
				access(lc, k, d);
			}
		}
	}

	return 0;
}
posted @ 2022-11-04 09:47  SkyRainWind  阅读(29)  评论(0编辑  收藏  举报