ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CSP 后多校十三(反悔贪心待补)

2021-11-12 21:33:34  阅读:133  来源: 互联网

标签:ch 待补 max long int 后多校 getchar CSP define


A. 嗑瓜子

简单的概率与期望,有很多方法来做.

可以选择正推概率,最后乘一个操作次数就是贡献,思路来自沈老师.

可以选择一遍推概率,一遍推步数( 其实没有什么卵用 ),从而得到期望,思路来自 \(fengwu\).

可以选择倒推期望,从结果入手,最后回到状态起点就是答案,思路来自 \(Amx\).

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long 
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
		for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
		for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
		return cit?(-w):w;
	};
} using namespace BSS;

const int N=5e3+21,mod=998244353;

int m,n,ans;
int inv[N<<2];
int dp[N][N];
signed main(){
	File(eat);
	n=read(),inv[1]=1;
	for(int i=2;i<=5e3;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	for(int i=1;i<=n;i++){
		for(int j=0;j<=n*2;j++){
			dp[i][j]=(dp[i-1][j+2]*i%mod*inv[i+j]%mod+1)%mod;
			if(j>0) dp[i][j]=(dp[i][j]+dp[i][j-1]*j%mod*inv[i+j]%mod)%mod;
		}
	}
	printf("%lld\n",dp[n][0]),exit(0);
}

B. 第 k 大查询

考虑什么东西可以暴力做,什么东西可以优化做.

这个题几乎就是很暴力,直接每次找到左边比自己大的 \(k\) 个数,右边比自己大的 \(k\) 个数,链表维护很方便.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	// #define int long long 
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
		for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
		for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
		return cit?(-w):w;
	};
} using namespace BSS;

#define LL long long 
const int N=5e5+21;

LL ans;
int m,n;
int val[N],pos[N],le[N],ri[N];
int con[N][2];
multiset<int> s;
vector<int> vec;
signed main(){
	File(kth);
	n=read(),m=read();
	for(int i=1;i<=n;i++) val[i]=read(),pos[val[i]]=i;
	for(int i=1;i<=n;i++) con[i][0]=i-1,con[i][1]=i+1;
	for(int i=1,lmi=n-m+1;i<=lmi;i++){
		int x=pos[i],cl=1,cr=1; le[cl]=x,ri[cr]=x;
		while(con[x][0] and cl<m) x=con[x][0],le[++cl]=x;
		x=pos[i];
		while(con[x][1]<=n and cr<m) x=con[x][1],ri[++cr]=x;
		if(cl+cr<=m) break;
		// cout<<"cl and cr:"<<cl<<' '<<cr<<endl;
		// for(int j=1;j<=cl;j++) cout<<le[j]<<' '; puts("");
		// for(int j=1;j<=cr;j++) cout<<ri[j]<<' '; puts("");
		for(int j=1;j<=cl;j++){
			if(m-j+1>cr) continue;
			// cout<<(con[ri[m-j+1]][1]-ri[m-j+1])<<' '<<(le[j]-con[le[j]][0])<<" skr\n";
			ans+=1ll*(con[ri[m-j+1]][1]-ri[m-j+1])*(le[j]-con[le[j]][0])*i;
		}
		x=pos[i];
		con[con[x][0]][1]=con[x][1];
		con[con[x][1]][0]=con[x][0];
	}
	printf("%lld\n",ans),exit(0);
}

C. 树上路径

可以显然地发现题目就是让求删掉一条边之后求左右两边联通块的最大直径,然后最大后缀和就可以了.

考虑怎么求,一个很直接的思路就是开一个 \(multiset\),但是发现有用的其实就只有前几个长度,于是维护就好了.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	// #define int long long 
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#define Fill(x,y) memset(x,y,sizeof(x))
	#define Copy(x,y) memcpy(x,y,sizeof(x))
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
		for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
		for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
		return cit?(-w):w;
	};
} using namespace BSS;

#define LL long long 
const int N=5e5+21;

LL ans;
int m,n,ts;
int head[N],maxn[N];
int f[N][2],g[N][2];
struct I { int u,v,nxt; } e[N<<1];
auto add=[](int u,int v)->void{
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u];
	head[u]=ts;
};
void sch(int u,int dad){
	for(int i=head[u],v;i;i=e[i].nxt){
		if((v=e[i].v)==dad) continue;
		sch(v,u),f[u][0]=max(f[u][0],f[v][0]);
		f[u][0]=max(f[u][0],g[v][0]+g[u][0]+1);
		g[u][0]=max(g[u][0],g[v][0]+1);
	}
}
void dfs(int u,int dad){
	int x=g[u][1],y=-1,z=-1,w=f[u][1];
	for(int i=head[u],v;i;i=e[i].nxt){
		if((v=e[i].v)==dad) continue;
		if(g[v][0]>=x) z=y,y=x,x=g[v][0];
		else if(g[v][0]>=y) z=y,y=g[v][0];
		else z=max(z,g[v][0]);
	}
	for(int i=head[u],v;i;i=e[i].nxt){
		if((v=e[i].v)==dad) continue;
		if(g[v][0]==x) f[v][1]=max(w,y+z+2),g[v][1]=y+1;
		else if(g[v][0]==y) f[v][1]=max(w,x+z+2),g[v][1]=x+1;
		else if(g[v][0]==z) f[v][1]=max(w,x+y+2),g[v][1]=x+1;
		w=max(w,f[v][0]); dfs(v,u);
	}	
}	
signed main(){
	File(tree);
	n=read(); int u,v;
	for(int i=2;i<=n;i++){
		u=read(),v=read(),add(u,v),add(v,u);
	}
	sch(1,0),g[1][1]=-1,dfs(1,0);
	for(int i=1;i<=n;i++) f[i][0]++,f[i][1]++;
	for(int i=1;i<=n;i++){
		maxn[f[i][1]]=max(maxn[f[i][1]],f[i][0]);
		maxn[f[i][0]]=max(maxn[f[i][0]],f[i][1]);
	}
	for(int i=n;i;i--) maxn[i]=max(maxn[i],maxn[i+1]),ans+=1ll*maxn[i];
	printf("%lld\n",ans),exit(0);
}

D. 糖

状态不太好,一直没搞太明白,先鸽一会儿.

标签:ch,待补,max,long,int,后多校,getchar,CSP,define
来源: https://www.cnblogs.com/AaMuXiiiiii/p/15546493.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有