Educational Codeforces Round 96 ABCDE 题解(详解)
A. Number of Apartments
题意:用3、5、7凑数,若能凑出给出方案,不能则输出-1。
思路:观察发现除了1 2 4凑不到以外其他都凑得到。那么关于方案的话,既然其他数都凑得到,我们就可以用dp的思想每次试探着来,若减去当前数还是个可以凑得到的就继续减直到等于0。
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
ll all[3] = {7,5,3};
ll Map[2000];
ll cnt[10];
int main()
{
int kase;
cin>>kase;
Map[1] = 1, Map[2] = 1, Map[4] = 1;
while(kase--)
{
ll n = read();
mem(cnt,0);
if(Map[n])
{
cout<<-1<<endl;
continue;
}
while(n)
{
rep(i,0,2) if(n-all[i]>=0&&!Map[n-all[i]])
{
cnt[all[i]]++;
n -= all[i];
break;
}
}
cout<<cnt[3]<<' '<<cnt[5]<<' '<<cnt[7]<<endl;
}
return 0;
}
B. Barrels
题意:有n个无限容量的水桶,现在各含a[i]的水,现在可以随便k次,问最大最小值差的最大值。
思路:水题,从次大的水桶开始倒k桶,全部倒进最大的那一桶。
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
ll a[maxn];
int main()
{
int kase;
cin>>kase;
while(kase--)
{
ll n = read(), k = read();
rep(i,1,n) a[i] = read();
sort(a+1,a+1+n);
int p = 1;
ll cnt = 1;
for(int i=n-1; i>=1&&cnt<=k; i--)
{
a[n] += a[i];
cnt++;
}
cout<<a[n]<<endl;
}
return 0;
}
C. Numbers on Whiteboard
题意:每次可以把任意两个数a,b替换成\(\lceil {(a+b)/2} \rceil\),可以操作n-1次,问最后剩下的一个数能达到的最小值是多少。并且输出每一步操作。
思路:从后面大的开始,先把a[n] a[n-2]变成a[n-1],再把两个a[n-1]结合变成1个a[n-1],然后就可以一路从a[n-3]往前平推,每次都会使得值-1。
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
typedef struct Ans
{
ll a;
ll b;
}A;
A ans[maxn];
int main()
{
int kase;
cin>>kase;
while(kase--)
{
ll n = read();
ll k = n-1;
if(n==2)
{
cout<<2<<endl;
cout<<1<<' '<<2<<endl;
continue;
}
ans[1].a = n;
ans[1].b = n-2;
ans[2].a = n-1;
ans[2].b = n-1;
int p = 2;
ll cur = n-1;
per(i,n-3,1)
{
ans[++p].a = cur;
ans[p].b = i;
cur = (cur+i+1)/2;
}
cout<<cur<<endl;
rep(i,1,p) cout<<ans[i].a<<' '<<ans[i].b<<endl;
}
return 0;
}
D. String Deletion
题意:给你一个01串,每一次操作必须先删掉任意一个位置,然后删除掉最长相同前缀。问最多能维持多少次这个操作。
思路:既然每次操作是对一个相同前缀下手,那我们就把每一块相同数所组成的联通块看成一个整体。同时记录他们的长度。
如1110010就可以看成
111 00 1 0
写成联通块(长度表示)
3 2 1 1
然后我们发现,会使得我们操作变少的是联通块长度为1的,我们现在想让1尽量的维持下去,即不让他在每次操作前减完自身使得要牺牲下一个联通块。
首先考虑到如果一个数大于1,那么“删除”这一步减自己就好了,不浪费别的。
而如果一个数等于1, 那我们就要考虑从它后面(轮到它当前缀时)找一些大于2的数(找2的话一减又多出个1来),这样就可以让它维持下去,删除前缀时就可以减掉当前的1而不影响后面一个。而找不到的话,那就只能减去当前这个1,然后再牺牲下一个联通块了(下一个联通块变成新的前缀)。
主要的思想就是上面说的,现在考虑怎么实现“在后面找一个大于2的数”,如果每个位置都往后找,那就是\(O(n^2)\)的时间复杂度,肯定不行。
我们发现当前i位置往后,若找到某个位置j来删除,那么在i+1位置,肯定也是从j开始往后找的,也就是前j-1个位置既然都不满足i位置,那么肯定也不满足i+1位置。这样我们只需要用双指针走一遍这个数组即可。时间复杂度\(O(2n)\)
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
string s;
ll block[maxn];
int p = 0;
ll solve()
{
int q = 1;
ll ans = 0;
bool flag = 0;
rep(i,1,p)
{
if(flag)
{
ans++;
i += 1;
continue;
}
if(block[i]>1) ans++;
else
{
while(q<i||(q<=p&&block[q] <= 1)) q++;
if(q>p)
{
flag = 1;
ans++;
i += 1;
}
else
{
block[q]--;
ans++;
}
}
}
return ans;
}
int main()
{
int kase;
cin>>kase;
while(kase--)
{
p = 0;
ll n = read();
string s;
cin>>s;
block[++p] = 1;
rep(i,1,n-1)
{
if(s[i]==s[i-1]) block[p]++;
else block[++p] = 1;
}
cout<<solve()<<endl;
}
return 0;
}
E. String Reversal
题意: 给一个字符串,每次可以相邻位置交换,问最少多少次可以使得字符串变成原来的颠倒字符串。
思路:显然有比直接一步步交换过去更优的策略。
比如acbac,我们想让第一个a变到最后一个位置去,完全不需要第一个位置的a动,只需要最靠近右边的a和c交换即可,一步到位。
所以策略就是每次都让最靠近右边的,和当前字符相同的字符移动就好。
但是这样会有个问题,就是有些位置被移动过,它左边的数再经过它往右交换时,距离就要减去这个空位。那怎么维护这个东西呢?
我们把这个“空位”产生的影响描述出来就是,一开始找到第一个位置的最靠右的相同字符,位置为p1,丢到最后,距离是n-p1。
然后第二个位置最靠右相同字符的位置p2, 若p2<p1,即p1这个空位对p2产生影响了,那就是n-p2-1。同理若p3<p2, 那就是n-p3-2。
所以就只需要统计p位置后面有多少空位即可,然后减去这个数。
这个时候树状数组的作用就来了。
为了方便,我们反过来看,从最后开始往前丢数,一开始是p1-1, 然后若p2>p1, 就p2-1-1,其次是p3-2-1(后面的-1是到1的距离,再减的就是空位个数)。所以我们的空位对计数是负贡献,把一开始[1,n]的区间每个位置都置为1, 一旦产生一个位置p产生空位,就在p这个位置-1,这样前缀和即表示(p-空位个数),每次的贡献就是前缀和-1。
view code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define endl '\n'
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 2e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
ll n;
string s;
queue<ll> q[50];
ll c[maxn];
inline int id(int p)
{
return s[p-1] - 'a' + 1;
}
inline void add(int p, ll val)
{
for(int i=p; i<=n; i+=lowbit(i)) c[i] += val;
}
inline ll ask(int p)
{
ll ans = 0;
for(int i=p; i>=1; i-=lowbit(i)) ans += c[i];
return ans;
}
int main()
{
n = read();
cin>>s;
rep(i,1,n) q[id(i)].push(i), add(i,1);
ll ans = 0;
per(i,n,1)
{
int pos = q[id(i)].front();
q[id(i)].pop();
ans += ask(pos)-1; add(pos, -1);
}
cout<<ans<<endl;
return 0;
}
Educational Codeforces Round 96 ABCDE 题解(详解)的更多相关文章
- Educational Codeforces Round 64 部分题解
Educational Codeforces Round 64 部分题解 不更了不更了 CF1156D 0-1-Tree 有一棵树,边权都是0或1.定义点对\(x,y(x\neq y)\)合法当且仅当 ...
- Educational Codeforces Round 64部分题解
Educational Codeforces Round 64部分题解 A 题目大意:给定三角形(高等于低的等腰),正方形,圆,在满足其高,边长,半径最大(保证在上一个图形的内部)的前提下. 判断交点 ...
- Educational Codeforces Round 63部分题解
Educational Codeforces Round 63 A 题目大意就不写了. 挺简单的,若果字符本来就单调不降,那么就不需要修改 否则找到第一次下降的位置和前面的换就好了. #include ...
- Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal 题解(思维+逆序对)
题目链接 题目大意 给你一个长度为n的字符串,可以交换相邻两个元素,使得这个字符串翻转,求最少多少种次数改变 题目思路 如果要求数组排序所需要的冒泡次数,那其实就是逆序对 这个也差不多,但是如果是相同 ...
- Educational Codeforces Round 96 (Rated for Div. 2) E. String Reversal (思维,逆序对)
题意:给你一个字符串,每次可以调换现字符串的相邻两个字符,问最少操作多少次使得这个字符串等于其反转过来的字符串. 题解:先考虑字符串中没有相同字符的情况,那么我们每次将目前字符串的最后一个字符一直调换 ...
- Educational Codeforces Round 96 (Rated for Div. 2) D. String Deletion (思维)
题意:有一个\(01\)串,每次操作要先删除一个位置上的元素,然后删除相同前缀和,直到字符串被删完,问最多能操作多少次. 题解: 对于一个长度大于\(1\)的相同前缀,我们最多只能对它操作一次,然后就 ...
- Educational Codeforces Round 96 (Rated for Div. 2)
A. Number of Apartments 题意:求方程的解 思路:直接模拟就行 代码: #include<iostream> #include<cstdio> #incl ...
- Educational Codeforces Round 16---部分题解
710A. King Moves 给你图中一点求出它周围有几个可达的点: 除边界之外都是8个,边界处理一下即可: #include<iostream> #include<cstdio ...
- Educational Codeforces Round 38 部分题解
D. Buy a Ticket 分析 建一个源点,连向所有结点,边的花费为那个结点的花费,图中原有的边花费翻倍,最后跑一遍最短路即可. code #include<bits/stdc++.h&g ...
- Educational Codeforces Round 110 A-D 题解
A. Fair Playoff 题目大意:有4个人进行比赛,第一个和第二个比,第三个和第四个比,之后各自的胜者再比,最开始每个人持有一个数字,每场比赛持有数字较大的选手会胜出,问最开始持有数字最大 ...
随机推荐
- idea的配置优化
一.显示工具条 二.设置鼠标悬浮提示 三.显示方法分隔符 四.忽略大小写提示 五.主题设置 如果需要很好看的编码风格,这里有很多主题 http://color-themes.com/?view=ind ...
- Spring Cloud Bus服务总线
一.Spring Cloud Bus是用轻量的消息代理将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理,也就是消息总线可以为微服务做监控,也可以实现应用程序之间相互通信,Sprin ...
- kettle使用MD5加密增量获取接口数据
kettle使用MD5加密增量获取接口数据 场景介绍: 使用JavaScript组件进行MD5加密得到Http header,调用API接口增量获取接口数据,使用json input组件解析数据入库 ...
- .net core分布式锁的实现(基于redis)
一.单个redis节点 实现原理:核心采用StackExchange.Redis的LockTake方法实现.支持同步获取锁,或者等待直到超时获取锁. 基于SENTX命令. copy一下文档的demo ...
- Vue相关笔记
Promise基本使用 Promise是异步编程的一种解决方案,用于一个异步操作的最终完成(或失败)及其结果值的表示,比传统的回调函数方案更加合理. var promise = new Promise ...
- 重载(Overloading)与重写(Override)的区别?
重载(Overloading)与重写(Override)的区别? No. 区别 重载 重写 1 英文单词 Overloading Override 2 发生范围 发生在一个类里面 发生在继承关系中 3 ...
- 【记录】ChatGPT|近期三次更新一览(更新至2023年2月3日)
如果你还没有使用过ChatGPT,可以先看看我的上一篇文章:[记录]ChatGPT|使用技巧与应用推荐(更新至2023年2月8日). 1月11号晚上,ChatGPT突然很多人都无法登录,包括我 ...
- TVM相关
TVM介绍 为解决深度学习框架和硬件后端适配问题,华盛顿大学的陈天奇等人提出了TVM. TVM是一个端到端的全栈编译器,包括统一的IR堆栈和自动代码生成方法,其主要功能是优化在CPU.GPU和其他定制 ...
- JuiceFS v1.3-Beta1:一亿文件备份分钟级完成,性能优化全解析
在最新发布的 JuiceFS v1.3 Beta1 版本中,我们引入了一种全新的二进制备份机制,旨在更高效地应对亿级文件规模下的备份与迁移场景.相比现有的 JSON 备份方式,该机制在导入导出元数据时 ...
- WindowsPE文件格式入门11.资源表
https://www.bpsend.net/thread-411-1-1.html 资源表 资源的管理方式采用windows资源管理器目录的管理方式,一般有三层目录. 根目录 结构体IMAGE_RE ...