Codeforces Round #742 (Div. 2) ABCDE题解

时间:2021-09-06
本文章向大家介绍 Codeforces Round #742 (Div. 2) ABCDE题解,主要包括 Codeforces Round #742 (Div. 2) ABCDE题解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

A 水题:直接'U'对应'D','D'对应'U',遇见LR复制一遍。

B 比较简单:预处理300000内的xor前缀异或,当xor[a-1]==b,直接0-->a即可。否则,如果xor[a-1]^b==a,那么需要0-->a-1以及另外两个数字xor得到a(避免直接用a)故a+1个数,如果xor[a-1]^b!=a,那么0-->a-1以及xor[a-1]^b这a+2个数。

C题:发现对于奇数位和双数位上的数相加,他们是分别并且独立的。例如15678 , 那么分离开168和57,我们发现只有分别满足两个数加和为168和57即可,那么他们方案数相乘。最后要减去2,因为有(0,数)和(数,0)的情况。

点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<bitset>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;

ll a[12],wz;
ll ans;
int main(){
	int t; scanf("%d",&t);
	while (t--) {
		ll n; wz = 0;
		scanf("%lld",&n);
		ans = 1;
		while (n) {
			a[++wz] = n%10;
			n/=10;
		}
		ll ad = 0; ll af = 0;
		for(int i=wz;i>=1;i-=2) {
			ad = ad*10ll + a[i];
		}
		for(int i=wz-1;i>=1;i-=2) {
			af = af*10ll + a[i];
		}
		ans = (ad+1)*(af+1)-2;
		printf("%lld\n",ans);
	}
	
	return 0;
}

D:其实就是一个模拟。。。我们发现只要拆分得尽可能不退位,退位先退低位就OK,代码写得比较复杂。。

点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<bitset>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>

using namespace std;
priority_queue<int,vector<int>,greater<int> > q;
int S,N,wz;
int a[15],po[15];
int main(){
	po[1] = 1;
	for(int i=2;i<=10;i++) po[i] = po[i-1]*10;
	int t; scanf("%d",&t);
	while (t--) {
		wz = 0;
		scanf("%d%d",&S,&N);
		int sum = 0;
		while (S) {
			a[++wz] = S%10;
			S /= 10;
			sum += a[wz];
		}
		if(sum>=N) {
			int hb = sum-N+1;
			int ans = 0;
			for(int i=1;i<=wz&&hb;i++) {
				while(a[i]&&hb) {
					hb--; 
					ans += po[i]; 
					a[i]--;
				}
			}
            printf("%d ",ans); N--;
            for(int i=1;i<=wz;i++) {
                while(a[i]) {
                    printf("%d ",po[i]); a[i]--;
                }
            }
            puts("");
			continue;
		} else {
            for(int i=2;i<=wz;i++) {
				for(int j=1;j<=a[i];j++) q.push(po[i]);
			}
			while(q.size()+a[1]<N) {
				int x = q.top(); q.pop();
				if(x==10) a[1] += 10;
				else {
					for(int j=1;j<=10;j++) q.push(x/10);
				}
			}
			int ans = 0;
			while(a[1]&&a[1]+q.size()>N-1) {
				a[1]--; ans++; 
			}
			while(q.size()>N-1) {
				ans += q.top(); q.pop();
			}
			printf("%d ",ans);
			while(a[1]) {
				printf("1 "); a[1]--;
			}
			while(q.size()) {
				printf("%d ",q.top()); q.pop();
			}
			puts(""); continue;
		}
	}
	
	return 0;
}

发现一种惊为天人的写法,还是太菜了(复制自xiaoziyao)

点击查看代码
#include<stdio.h>
#include<math.h>
int T,n,m;
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);
		for(int i=1;i<m;i++){
			int j=pow(10,(int)log10(n-(m-i)));
			printf("%d ",j),n-=j;
		}
		printf("%d\n",n);
	}
	return 0;
}

E:一道线段树基本题吧,算是帮我彻彻底底地复习了一遍线段树,也算是大有收获吧。

本题开结构体记录一段数列:1 前缀连续最长不降 2 后缀连续最长不降 3 最左数 4 最右数 5该段包含答案对数 6该整段是否都是连续不降的

这样转移方式与维护方式就很简单了,有点像小白逛公园。

点击查看代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<bitset>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#define ll long long
using namespace std;
const int maxn = 400005;
int n,q;
int a[maxn];
int tot,ls[maxn],rs[maxn],rt;

struct node {
	int lonpre,lonsuf,ln,rn;
	bool se;
	ll tt;
}z[maxn];

void init(int p,int x) {
	z[p].lonpre = z[p].lonsuf = z[p].se = z[p].tt = 1;
	z[p].ln = z[p].rn = a[x];
}
node operator+(node aa,node bb) {
	node cc;
	if(aa.se&&bb.se&&aa.rn<=bb.ln) cc.se = 1; else cc.se = 0;
	cc.lonpre = (aa.se&&aa.rn<=bb.ln) ? aa.lonpre + bb.lonpre : aa.lonpre;
	cc.lonsuf = (bb.se&&aa.rn<=bb.ln) ? bb.lonsuf + aa.lonsuf : bb.lonsuf;
	cc.tt = aa.tt + bb.tt + ( (aa.rn<=bb.ln) ? 1ll * aa.lonsuf * bb.lonpre : 0 ) ;
	cc.ln = aa.ln; cc.rn = bb.rn;
	return cc;
}
int maketree(int l,int r) {
	int p = ++tot;
	if(l==r) {
		init(p,l);
		return p;
	}
	int mid = (l+r)>>1;
	ls[p] = maketree(l,mid);
	rs[p] = maketree(mid+1,r);
	z[p] = z[ls[p]] + z[rs[p]];
	return p;
}
void update(int p,int l,int r,int x) {
	if(l==r) {
		init(p,l);
		return;
	}
	int mid = (l+r)>>1;
	
	if(x<=mid) update(ls[p],l,mid,x); 
	else update(rs[p],mid+1,r,x);
	z[p] = z[ls[p]] + z[rs[p]];
}
node query(int p,int l,int r,int x,int y) {
	if(x<=l&&r<=y) return z[p];
	int mid = (l+r)>>1;
	if(x>mid) return query(rs[p],mid+1,r,x,y);
	else if(y<=mid) return query(ls[p],l,mid,x,y);
	else return query(ls[p],l,mid,x,y) + query(rs[p],mid+1,r,x,y);
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
	}
	rt = maketree(1,n);
	int ty,x,y;
	while(q--) {
		scanf("%d%d%d",&ty,&x,&y);
		if(ty==1) {
			a[x] = y;
			update(rt,1,n,x);
		} else {
			printf("%lld\n",query(rt,1,n,x,y).tt);
		}
	}
	 
	return 0;
}

F暂时待续吧。。。

原文地址:https://www.cnblogs.com/newuser233/p/cf742.html