昨晚的div2算是拿下了,终于上了绿名,开心.
腐乳manjuan,出列!
把复活赛的I题补了,很好的一道题啊
题意:自行理解
思路:题意很好理解,但思路不好出,什么树状数组,dp之类的都不行。实际上这道题需要逆向思维,一个一个删除处理不了,就变为处理倒着一个一个加上去,然后用并查集维护。虽然思路网上看的,但代码实现还是我自己敲的,挺满意。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e5+10,M=1e9+10;
int n;
int a[N],p[N];
int fa[N];
bool vi[N];
vector<ll>ve;
ll sum[N],tmp;
int fnd(int x){
return fa[x]==x?x:fa[x]=fnd(fa[x]);
}
void solve(){
cin >> n;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=n;i++){
cin >> a[i];
sum[i]=a[i];
}
for(int i=1;i<=n;i++){
cin >> p[i];
}
for(int i=n;i;i--){
vi[p[i]]=1;
if(vi[p[i]-1] && vi[p[i]+1]){
int x=fnd(p[i]-1),y=fnd(p[i]+1);
fa[x]=p[i],fa[y]=p[i];
sum[p[i]]+=sum[x],sum[p[i]]+=sum[y];
ve.push_back(max(sum[p[i]],tmp));
tmp=max(sum[p[i]],tmp);
}else if(vi[p[i]-1]){
int x=fnd(p[i]-1);
fa[x]=p[i];
sum[p[i]]+=sum[x];
ve.push_back(max(sum[p[i]],tmp));
tmp=max(sum[p[i]],tmp);
}else if(vi[p[i]+1]){
int x=fnd(p[i]+1);
fa[x]=p[i];
sum[p[i]]+=sum[x];
ve.push_back(max(sum[p[i]],tmp));
tmp=max(sum[p[i]],tmp);
}else{
ve.push_back(max(sum[p[i]],tmp));
tmp=max(sum[p[i]],tmp);
}
}
for(int i=ve.size()-2;i>=0;i--) cout << ve[i] << endl;
cout << 0;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
复活赛的F题,虽然现在有点看不懂,但标记一下:
题意:从0,0点向右上射出一道光,直到被任一角落吸收,问第一次经过k个传感器的时间,如没经过,输出-1。
思路:没有思路,网上说是要用扩展欧几里得,看来确实得学习新的算法了,不然如康康所说,会遇到瓶颈。
但在这之前,让我们先来解决一道暴力
题意:自行理解
思路:暴力,想了半天不到怎么暴,搜了下发现是道1500分的题,洛谷上是黄题,倍受打击
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+5;
int n,m;
int a[44][44];
void swp(int x,int y){
for(int i=1;i<=n;i++){
swap(a[i][x],a[i][y]);
}
}
bool check(int b[44][44]){
for(int i=1;i<=n;i++){
int cnt=0;
for(int j=1;j<=m;j++){
if(b[i][j]!=j) cnt++;
}
if(cnt!=0 && cnt!=2) return 0;
}
return 1;
}
void solve(){
cin >> n >> m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin >> a[i][j];
}
}
if(check(a)){cout << "YES"; return ;}
for(int i=1;i<m;i++){
for(int j=i+1;j<=m;j++){
swp(i,j);
if(check(a)){cout << "YES"; return ;}
swp(i,j);
}
}
cout << "NO";
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期二:
和李,强打了场vp,22年江西省赛,打之前以为江西赛不会很难,结果。。
签到题3道做了俩,也都没有必要放上来。
标记一下E题(因为实在找不到题解,然后要用的算法还不会):
题意:将一数以数位拆解成k段(自由拆解),要求第一段和最后一段位数和的奇偶性相同,第二段和倒数第二段,以此类推,问有多少拆分方案
思路:据出题人说是区间dp+前缀和优化,我读题时也想到了可能是dp,但我不会dp啊,然后网上根本找不到这场比赛的题解,只能等以后有缘再来补。
然后看了下G题的思路,分类讨论。
星期三:
古早每日三题(trial 40)A题:
题意:自行理解
思路:一眼构造,不过不是很难的。ac后看了看网上有说欧拉回路什么的,不过不懂。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n,k;
int cnt;
void solve(){
cin >> n >> k;
while(cnt<n){
for(int i=1;i<=k;i++){
for(int j=i;j<=k;j++){
cout << (char)('a'+j-1),cnt++;
if(cnt==n) break;
if(j!=k) cout << (char)('a'+i-1),cnt++;
if(cnt==n) break;
}
if(cnt==n) break;
}
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
// cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期四:
挂道pta的题
题意:见题面
思路:第一次存棵树,后面的输入拿来比较。他这里有个很坑的点,数组必须初始化为-1,但题面上又写的给正整数,卡我老半天时间,恶心len。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e6+10;
int n,l;
int a[N],b[N];
bool cmp(int a[N],int b[N]){
for(int i=1;a[i];i++){
if(a[i]!=b[i]) return 0;
}
return 1;
}
void solve(){
while(cin >> n >> l && n){
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++){
int tmp;
cin >> tmp;
int j=1;
while(a[j]){
if(tmp<a[j]) j*=2;
else j=j*2+1;
}
a[j]=tmp;
}
while(l--){
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++){
int tmp;
cin >> tmp;
int j=1;
while(b[j]){
if(tmp<b[j]) j*=2;
else j=j*2+1;
}
b[j]=tmp;
}
if(cmp(a,b)) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
古早每日三题(同上)的B题:
算了题太长不截屏了。
题意:n条链子,找最大环。
思路:当成模拟写了俩天,wa4,然后上网一搜,贪心。。原来那代码也挺长的,懒得贴出来了。
星期五:
古早每日三题(同上)的C题:
题意:自行理解
思路:最开始当贪心模拟做,wa7,然后看网上二分,又用二分写了遍,wa7。。
结果是要当二分答案来写,代码异常简洁,如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n,z;
int x[N];
int ans;
bool check(int mi){
for(int i=mi;i;i--){
if(x[n-mi+i]-x[i]<z) return 0;
}
return 1;
}
void solve(){
cin >> n >> z;
for(int i=1;i<=n;i++) cin >> x[i];
sort(x+1,x+n+1);
int l=0,r=n/2;
while(l<=r){
int mid=l+(r-l)/2;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
cout << ans;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
// cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
星期六:
为了适应下重庆赛的时间,早上9点开始vp 第四届辽宁省赛,但脑子一直动不起来,基本都是强在框框写。赛前得调整下,要是17号我还是这状态,感觉会寄。
先贴俩题,然后再看情况补几道。
B题:
题意:如题
思路:先枚举,再二分。然后四舍五入这个操作,还好我以前用过(给出表面积,求最大体积的三分题),马上操作了出来。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n;
double a;
bool check(int x){
int l=1,r=x;
while(l<=r){
int mid=l+(r-l)/2;
if(round(1.0*mid/x*10000)/100>a) r=mid-1;
else if(round(1.0*mid/x*10000)/100<a) l=mid+1;
else return 1;
}
return 0;
}
void solve(){
cin >> a;
for(int i=1;i<=10000;i++) if(check(i)){cout << i; return ;}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
// cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
开始补题环节:
L题:
题意:见题
思路:朴素算法可以跑到1e15,一眼数据结构题,但不会。
补算法的话有点难,好像要用莫队+树状数组。
又学了遍dij最短路算法。
周日:
8点20开始vp 21年山东省赛,全程汗流浃背ac了3道题,先贴道签到题。
题意:给n个数,输出其平均数至小数点后k位(n,k可达1e5)
思路:1e5的精度,double再怎么long都得寄,得边算边输出,可能是高精度的知识,但没学过不影响签到。(ps.299队17队爆0)
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e5+10;
int n,k;
int a;
void solve(){
cin >> n >> k;
for(int i=1;i<=n;i++){
int tmp;
cin >> tmp;
a+=tmp;
}
cout << a/n << '.';
a%=n;
while(k--){
a*=10;
cout << a/n;
a%=n;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
// cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
补M题:
题意:构造,构造了近四个小时没构出来,看完题解又觉得不应该,还是构造题做少了。
思路:c为1,都为1。a最左列为1,最右列为0,b反之。a奇数行为1,偶数行为0,b反之。
代码如下:
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;
const int N=1e6+10;
int n,m;
char c[550][550];
void solve(){
cin >> n >> m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin >> c[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j==1) cout << 1;
else if(j==m) cout << 0;
else if(c[i][j]=='1') cout << 1;
else if(i&1) cout << 1;
else cout << 0;
}
cout << endl;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j==m) cout << 1;
else if(j==1) cout << 0;
else if(c[i][j]=='1') cout << 1;
else if(i&1) cout << 0;
else cout << 1;
}
cout << endl;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t=1;
//cin >> t;
while(t--) solve();
return 0;
}
//make it count
//开ll plz
补c题:
题意:树上点可为白色或黑色,黑点子树节点必须全为黑。给一k为染色方案,要求输出一颗刚好k种染色方案的树。
思路:3号没补上这题,看下周的吧