日常刷题2025-3-5

日常刷题2025-3-5

P8472 [Aya Round 1 G] 咕噜论坛(post)

绿色

https://www.luogu.com.cn/problem/P8472

正解:双指针

本题不是一维数组,而是二维矩阵,对于一维数组枚举区间,我们需要枚举起点和终点,时间复杂度是O(n2)的。对于二维矩阵,我们需要枚举矩形的四个边,时间复杂度是O(n4)的。在本题中,左边条竖边用了双指针优化,所以可以不用枚举,时间复杂度降为O(n3),可以通过此题。

此题非常具有参考价值!!!

代码

#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
const int MAXN=500+3;
int A[MAXN][MAXN],B[MAXN][MAXN],C[MAXN][MAXN];
int qry(int T[][MAXN],int l1,int l2,int r){
return T[l2][r]-T[l1-1][r];
}
char S[MAXN][MAXN];
int n,m,k;
int qread(){
int w=1,c,ret;
while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*w;
}
int ans=-1,a1,a2,a3,a4,a5;
int main(){
n=qread(),m=qread(),k=qread();
up(1,n,i) scanf("%s",S[i]+1);
up(1,n,i) up(1,m,j){
A[i][j]=(S[i][j]=='P')+A[i-1][j];
B[i][j]=(S[i][j]=='B')+B[i-1][j];
C[i][j]=(S[i][j]=='G')+C[i-1][j];
}
up(1,n,i) up(i,n,j){
int sp=0,sb=0,sg=0,lp=1,lb=1,lg=1,x=j-i+1;
up(1,m,r){
int wp=qry(A,i,j,r); sp+=wp;
int wb=qry(B,i,j,r); sb+=wb;
int wg=qry(C,i,j,r); sg+=wg;
if(wp ) lb=r+1,lg=r+1,sb=sg=0;
if(wb||wg) lp=r+1,sp=0;
// while(lp<=r&&x*(r-lp+1)-sp>k) sp-=qry(A,i,j,lp),++lp; 此行代码是不必要的
while(lb<=r&&x*(r-lb+1)-sb>k) sb-=qry(B,i,j,lb),++lb;
while(lg<=r&&x*(r-lg+1)-sg>k) sg-=qry(C,i,j,lg),++lg;
if(x*(r-lp+1)>ans) ans=x*(r-lp+1),a1=i,a2=lp,a3=j,a4=r,a5='P';
if(x*(r-lb+1)>ans) ans=x*(r-lb+1),a1=i,a2=lb,a3=j,a4=r,a5='B';
if(x*(r-lg+1)>ans) ans=x*(r-lg+1),a1=i,a2=lg,a3=j,a4=r,a5='G';
}
}
up(a1,a3,i) up(a2,a4,j) S[i][j]=a5;
printf("%d\n",ans);
up(1,n,i) printf("%s\n",S[i]+1);
return 0;
}

P8590 『JROI-8』这是新历的朝阳,也是旧历的残阳

绿色

https://www.luogu.com.cn/problem/P8590

正解:双指针+公式化简

三个重要的点

  • 题目中给的数组是单调不减的数组

  • 由于中间可以插入空区间,所以为了让答案最大正数无脑放到最后一个区间,对于负数满足(ai+1)2>=(ai+m)2ai分到第一段,其余的负数分到最后一段。所以一定会存在一个分界点t,分界点左边满足公式i=1t(ai+1)2,右边满足i=t+1n(ai+m)2

  • 当m增大时,只可能会有更多的负数被分到右边,所以 m 增大,t 不会右移,这是可以双指针的基础。

根据第二个点,我们需要对公式进行化简。

具体过程参考题解https://www.luogu.com.cn/article/1h6k19g9

评述

没有好好看题,完全不知道数组单调不减这个信息,搞得连划分方法都没想到。还有就是我对公式一点都不敏感,看到公式根本就不想化简。

代码

#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
//long long也是要开的
int n,k;
int ans;
int a[1000005];
int s1,s2;
signed main(){
ios::sync_with_stdio(0);
cin>>n>>k;
int t=n;
for(int i=1;n>=i;i++)cin>>a[i];
for(int i=1;n>=i;i++){
ans=(ans+(a[i]*a[i])%mod)%mod;
s1=(s1+a[i])%mod;//前缀和
}
ans=(ans*k)%mod;//直接在最开始就将序列平方和乘上k,在循环时不用单独计算。
for(int i=1;k>=i;i++){
while((a[t]+1)*(a[t]+1)<(a[t]+i)*(a[t]+i)&&t){
s1=(s1-a[t]+mod)%mod;s2=(s2+a[t])%mod;
t--;//对于每个m,更新t和s1,s2。
}
ans=(ans+(((i*i)%mod)*(n-t))%mod+t+(2*s1)%mod+(2*i*s2)%mod+mod)%mod;
//注意取模。
}
cout<<ans<<endl;
return 0;
}

本文作者:califeee

本文链接:https://www.cnblogs.com/califeee/p/18751950

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   califeee  阅读(1)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.