• 【CSP-S 2019题解】


    CSPSCSP-S之后可以说半条腿退役了
    如果没那一个失误的话rk14rk14还有救

    感觉现在对OIOI的感情也挺复杂的
    有些东西自己也还没想明白


    Day1

    T1T1

    模拟即可

    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define pb push_back
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    #define ull unsigned long long
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    inline ull readu(){
    	char ch=gc();
    	ull res=0;
    	while(!isdigit(ch))ch=gc();
    	while(isdigit(ch))res=(res*10)+(ch^48),ch=gc();
    	return res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    ull k;
    int n,ans[100];
    void solve(int pos,ull ret){
    	if(pos==1){
    		ans[pos]=ret;
    		return;
    	}
    	ull mid=1;
    	mid=mid<<(pos-1);
    	mid-=1;
    	if(ret<=mid){
    		ans[pos]=0;solve(pos-1,ret);return;
    	}
    	else{
    		ans[pos]=1;
    		solve(pos-1,mid-ret+mid+1);
    		return;
    	}
    }
    int main(){
    	freopen("code.in","r",stdin);
    	freopen("code.out","w",stdout);
    	n=read(),k=readu();
    	solve(n,k);
    	for(int i=n;i;i--)cout<<ans[i];
    	return 0;
    }
    

    T2T2

    考场debuffdebuff太严重了
    不知道为什么这傻逼题就是没想明白

    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define re register
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    inline void readstring(char *s){
    	int top=0;
    	char ch=gc();
    	while(isspace(ch))ch=gc();
    	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
    }
    cs int N=500005;
    char s[N];
    int fa[N],pf[N];
    int n;
    ll anc[N];
    vector<int> e[N];
    void dfs(int u){
    	pf[u]=pf[fa[u]];
    	if(s[u]=='(')pf[u]=u;
    	else if(pf[u]>0){
    		anc[u]=anc[fa[pf[u]]]+1;
    		pf[u]=pf[fa[pf[u]]];
    	}
    	for(int &v:e[u])dfs(v);
    }
    void dfs2(int u){
    	for(int &v:e[u]){
    		anc[v]+=anc[u];
    		dfs2(v);
    	}
    }
    int main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#endif
    	n=read();
    	readstring(s);
    	for(int i=2;i<=n;i++)fa[i]=read(),e[fa[i]].pb(i);
    	dfs(1),dfs2(1);
    	ll ret=0;
    	for(int i=1;i<=n;i++)ret^=1ll*i*anc[i];
    	cout<<ret;
    }
    

    T3T3

    不会

    Day2Day2

    T1T1

    先无视n2lceilfrac n 2 ceil的条件,dpdp出总方案
    然后容斥用背包dpdp算方案
    只需要记使用这个食材和没使用的差即可

    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int mod=998244353;
    inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
    inline int dec(int a,int b){return (a-=b)<0?(a+mod):a;}
    inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
    inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
    inline void Dec(int &a,int b){(a-=b)<0?(a+=mod):0;}
    inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    cs int N=105,M=2005,L=103;
    char xxx;
    int g[N][N],s[N],a[N][M],f[N][2*N];
    int n,m;
    char yyy;
    inline int calc(int p){
    	f[0][L]=1;
    	for(int i=1;i<=n;i++){
    		for(int j=L-i;j<=L+i;j++){
    			f[i][j]=f[i-1][j];
    			if(j)Add(f[i][j],mul(f[i-1][j-1],a[i][p]));
    			Add(f[i][j],mul(f[i-1][j+1],dec(s[i],a[i][p])));
    		}
    	}
    	int res=0;
    	for(int k=L+1;k<=L+n;k++)
    	Add(res,f[n][k]);
    	return res;
    }
    int main(){
    	freopen("meal.in","r",stdin);
    	freopen("meal.out","w",stdout);
    	n=read(),m=read();
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){
    			a[i][j]=read();
    			Add(s[i],a[i][j]);
    		}
    	}
    	g[0][0]=1;
    	for(int i=1;i<=n;i++)
    	for(int j=0;j<=i;j++){
    		Add(g[i][j],g[i-1][j]);
    		if(j)Add(g[i][j],mul(g[i-1][j-1],s[i]));
    	}
    	int res=0;
    	for(int i=1;i<=n;i++)Add(res,g[n][i]);
    	for(int i=1;i<=m;i++){
    		memset(f,0,sizeof(f));
    		Dec(res,calc(i));
    	}
    	cout<<res<<'
    ';
    	return 0;
    } 
    

    T3T3

    如果有结论的话回来看证明也挺显然的
    但就是没想到

    可以直接看毛爷爷的题解

    感性伪 证明其实可以考虑把一个序列a1...ana_1...a_n分成递增的2段
    那么一定是在位置jj满足a1+...+aj<=aj+1+...+ana_1+...+a_j<=a_{j+1}+...+a_n
    a1+...+aj+1>aj+2+....+ana_1+...+a_{j+1}>a_{j+2}+....+a_n切开
    那么也就是说分界点一定要尽量靠后

    然后单调队列找分解点即可

    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll unsigned long long
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=40000005,M=100005;
    char xxx;
    int n,type,l[M],r[M],p[M],b[N],q[N],pre[N],hd,tl;
    ll a[N];
    char yyy;
    void write(__int128 x){
    	if(x>9)write(x/10);
    	putchar((x%10)+'0');
    }
    inline void getans(){
    	__int128 ret=0;
    	for(int i=n;i;i=pre[i]){
    		ret+=(__int128)(a[i]-a[pre[i]])*(a[i]-a[pre[i]]);
    	}
    	write(ret);
    }
    int main(){
    	n=read(),type=read();
    	if(type==0){
    		for(int i=1;i<=n;i++)a[i]=read()+a[i-1];
    	}
    	else{
    		ll x=read(),y=read(),z=read();int m;cs ll bas=(1<<30)-1;
    		b[1]=read(),b[2]=read(),m=read();
    		for(int i=1;i<=m;i++)p[i]=read(),l[i]=read(),r[i]=read();
    		for(int i=3;i<=n;i++)b[i]=(x*b[i-1]+y*b[i-2]+z)&bas;
    		for(int i=1,j=1;i<=n;i++){
    			if(i>p[j])j++;
    			a[i]=(b[i]%(r[j]-l[j]+1))+l[j];
    		}
    		for(int i=1;i<=n;i++)a[i]+=a[i-1];
    	}
    	for(int i=1;i<=n;i++){
    		while(hd<tl&&(a[q[hd+1]]*2-a[pre[q[hd+1]]])<=a[i])hd++;
    		pre[i]=q[hd];
    		while(hd<=tl&&(a[q[tl]]*2-a[pre[q[tl]]])>=(a[i]*2-a[pre[i]]))tl--;
    		q[++tl]=i;
    	}
    	getans();
    	return 0;
    }
    

    T3T3

    考场已经想出做法了但觉得时间不够为了保险就没去写

    直接考虑一个点会有多少边对其有贡献
    分成三个部分考虑:
    到根的链上的,到根链上点的其他子树的,子树内的

    记子树内最大的sizsizcc,一条边断开后子树内的sizsizss
    到根链上的需要满足2(ssiz)s,2cs2(s-siz)le s,2cle s
    2cs2siz2cle sle 2siz

    其他子树的即
    2(nssiz)ns,2cns2(n-s-siz)le n-s,2cle n-s
    n2sizsn2cn-2sizle sle n-2c

    对于子树内需要考虑是哪颗子树
    也可以做但比较麻烦
    一个方法是以重心做根
    那么对于重心以外的点就都不需要考虑子树
    对于重心只需要考虑最大的子树和其他子树两种情况即可

    然后就完了
    为什么我考场不去写啊,傻逼透了

    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=300005;
    int n;
    int rt,siz[N],mc[N];
    ll ans;
    vector<int> e[N];
    struct bit{
    	int tr[N];
    	#define lb(x) (x&(-x))
    	inline void clear(){
    		memset(tr,0,sizeof(tr));
    	}
    	inline void update(int p,int k){
    		for(;p<=n;p+=lb(p))tr[p]+=k;
    	}
    	inline int ask(int p,int res=0){
    		for(;p>0;p-=lb(p))res+=tr[p];
    		return res;
    	}
    	inline int query(int l,int r){
    		return ask(r)-ask(l-1);
    	}
    }s1,s2;
    void dfs1(int u,int fa){
    	siz[u]=1;
    	bool fg=1;
    	for(int &v:e[u]){
    		if(v==fa)continue;
    		dfs1(v,u);
    		siz[u]+=siz[v];
    		if(siz[v]>(n>>1))fg=0;
    	}
    	if(n-siz[u]>(n>>1))fg=0;
    	if(fg)rt=u;
    }
    void dfs2(int u,int fa){
    	siz[u]=1,mc[u]=0;
    	for(int &v:e[u]){
    		if(v==fa)continue;
    		dfs2(v,u);
    		siz[u]+=siz[v];
    		
    		chemx(mc[u],siz[v]);
    	}
    }
    void colc(int u,int fa,int k){
    	s1.update(siz[u],k);
    	for(int &v:e[u]){
    		if(v==fa)continue;
    		colc(v,u,k);
    	}
    }
    int cnt;
    void dfs3(int u,int fa,int lim){
    	s2.update(siz[u],1);
    	ans+=1ll*u*(s1.query(n-2*siz[u],n-2*mc[u])+s2.query(2*mc[u],2*siz[u]));
    	if(siz[u]<=lim)ans+=rt,cnt++;
    	for(int &v:e[u]){
    		if(v==fa)continue;
    		dfs3(v,u,lim);
    	}
    	s2.update(siz[u],-1);
    }
    inline void solve(){
    	s1.clear(),s2.clear();
    	ans=rt=cnt=0,n=read();
    	for(int u,v,i=1;i<n;i++){
    		u=read(),v=read();
    		e[u].pb(v),e[v].pb(u);
    	}
    	dfs1(1,0);
    	dfs2(rt,0);
    	int mx=0,semx=0;
    	for(int &v:e[rt]){
    		if(siz[v]>siz[mx])semx=mx,mx=v;
    		else if(siz[v]>siz[semx])semx=v;
    		colc(v,rt,1);
    	}
    	for(int &v:e[rt]){
    		colc(v,rt,-1);
    		if(v==mx)dfs3(v,rt,n-2*siz[semx]);
    		else dfs3(v,rt,n-2*siz[mx]);
    		colc(v,rt,1);
    	}
    	cout<<ans<<'
    ';
    	for(int i=1;i<=n;i++)e[i].clear();
    }
    int main(){
    	int T=read();
    	while(T--)solve();
    }
    
  • 相关阅读:
    事件总线2
    微信小程序视频录制教程
    vue插件开发-toast
    云计算中的测试,可从哪些维度入手
    ES配置及FAQ
    Azkaban安装及问题
    python 反编译 compileall
    平凡利用redis进行数据读写的一种优化
    彻底弄懂Redis的内存淘汰策略
    c# 判断年龄精确到日
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328355.html
Copyright © 2020-2023  润新知