首页 > 其他分享 >[NOIP2022] 种花

[NOIP2022] 种花

时间:2022-11-26 21:45:31浏览次数:55  
标签:dn int sum long times 种花 ans NOIP2022

没进 noip 的场外菜鸡选手。

Solution

可以发现 CF 的相似之处在于左侧都有一条竖线,可以枚举这一条竖线,设它的上顶点向右可以拓展 \(a\) 个格子,下顶点向右可以拓展 \(b\) 个,下顶点向下可以拓展 \(c\) 个。

那么显然,该竖线对于 C 的贡献就是 \(a\times b\),对于 F 的贡献就是 \(a\times b\times c\)。可以做到预处理 \(O(n^2)\),枚举竖线 \(O(n^3)\)。

考虑优化,计算一个上顶点对于答案的贡献,如图:

红色节点最多拓展到绿色节点,那么在我们枚举竖线的过程中,对 C 的贡献为 \(\sum a\times b_i\) 即 \(a\sum b_i\),其中 \(i\) 为向下能够拓展到的节点。预处理 \(b_i\) 前缀和。

同理,设一个点能向下拓展 \(c\) 格,枚举上顶点,对 F 的贡献为 \(\sum a\times b_i\times c_i\) 即 \(a\sum b_i\times c_i\)。预处理 \(b_i\times c_i\) 前缀和。

这样,就可以枚举每个点然后 \(O(1)\) 计算贡献了,预处理和计算答案的复杂度均为 \(O(n^2)\)。

Code

可能稍微繁琐一点,有注释。

#include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pb push_back
#define mkp make_pair
using namespace std;
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using ull=unsigned long long;
inline void read(int &x){
  char ch=getchar();
  int r=0,w=1;
  while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
  while(isdigit(ch))r=(r<<1)+(r<<3)+(ch^48),ch=getchar();
  x=r*w;
}
const int N=1007,mod=998244353;
int n,m,c,f,r[N][N],dn[N][N],sum[N][N],sum2[N][N];
char ok[N][N];
int getc(){
  int ans=0;
  for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    if(dn[i][j]>=3&&ok[i][j]=='0')//至少3格
    ans=(ans+(r[i][j]-1)*(sum[i+dn[i][j]-1][j]-sum[i+1][j])%mod)%mod;//注意顶点下方的第一个没有贡献
  return ans;
}
int getf(){
  int ans=0;
  for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
    if(dn[i][j]>3&&ok[i][j]=='0')//至少4格
    ans=(ans+(r[i][j]-1)*(sum2[i+dn[i][j]-2][j]-sum2[i+1][j])%mod)%mod;
  return ans;
}
void init(){
  memset(r,0,sizeof r);memset(dn,0,sizeof dn);
  for(int i=1;i<=n;i++)for(int j=m;j>=1;j--)
    r[i][j]=ok[i][j]=='1'?0:r[i][j+1]+1;//向右最多拓展几个
  for(int j=1;j<=m;j++)for(int i=n;i>=1;i--)
    dn[i][j]=ok[i][j]=='1'?0:dn[i+1][j]+1;//向下
  //这里拓展的都包含了自己本身,所以调用时要减1
  for(int j=1;j<=m;j++)for(int i=1;i<=n;i++)sum[i][j]=sum[i-1][j]+r[i][j]-1;//前缀和
  for(int j=1;j<=m;j++)for(int i=1;i<=n;i++)sum2[i][j]=sum2[i-1][j]+(r[i][j]-1)*(dn[i][j]-1);
}
void solve(){
  read(n);read(m);read(c);read(f);
  for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>ok[i][j];
  init();
  printf("%lld %lld\n",getc()*c,getf()*f);
}
main(){
  int T,id;read(T);read(id);
  while(T--)solve();
  return 0;
}

标签:dn,int,sum,long,times,种花,ans,NOIP2022
From: https://www.cnblogs.com/LAK666/p/16928305.html

相关文章

  • 【赛后总结】NOIP2022
    如果时间安排合理能否拿到更多的分。我不知道该说什么,想哭想大声喊寄想做一切……好像也没什么能做的,除了把t3的状压调出来。从t3,重新开始吧。时间安排8:27--8:45看......
  • NOIP2022 游记——终末之诗
    本来这个游记起名是终幕之礼的,结果谁知道这场直接把我送退役了。坐标ZJ。Day0:考前日常刷板子,去杭州之前我奶了一口“NOIP和CSP不一样,CSP会出三道图论,NOIP总不会出......
  • NOIP2022游记
    day-6上午集训的题不会做,洛谷月赛也不会做,可以埋了。下午不知道干了啥。晚上把月赛T1写了,顺便学了个线段树合并。感觉很慌啊。day-5上午比赛只会打暴力,可以埋了。下......
  • NOIP2022 游记
    进场前的想法是:过掉前两题,后两题暴力苟住,感觉这样大不至于挂太惨所以心态还行。8:25发了包的解压密码,但是看不了题,于是瞅了眼包。看barrack是计数,很好,看match像个ds......
  • NOIP2022游记
    2022.11.266:30前一天晚上10点看着象棋分解就神奇的睡着了(虽然晚上睡得不安稳,但是总归获得了难得充足的睡眠。洗漱,吃了放在房间门口的早餐,就该集合了。7:10被领着到酒......
  • 【比赛游记】NOIP2022 游记
    Day0终于在今年,开通了从长乐至福州的地铁。从长乐航城到福州苍山的话,可以坐六号线转一号线,大致路线是郑和\(\to\)梁厝\(\to\)三叉街。1:20抵达希尔顿惠庭酒店(四......
  • NOIp2022 rp++
    rp++!mark:复赛时要记住的30句话如何在联赛和省选中进行暴力和骗分?比赛进行的时候你应该干什么?打满暴力,暴力不挂!剪枝多跑出来一点!希望能蹭到三倍队线!......
  • NOIP2022 游记
    Day0摆烂。Day1来到了考场床,开始睡觉。睡了一上午,醒来之后发现已经12:30了,赶紧开题,发现没题,剩下的时间就睡觉了。期望得分0+0+0+0=0。不过CCF数据水,......
  • LeetCode 605.种花问题
    LeetCode605.种花问题题目链接:​​https://leetcode-cn.com/problems/can-place-flowers/​​题目描述:假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不......
  • NOIP2022 游记
    NOIP2022游记Hello,hello,helloworld.Iopenmyeyesandsaidhellototheworld.——《HelloWorld》Day-2被hh的神秘模拟赛打自闭了。2hard4me.希望......