【BZOJ2727】双十字(动态规划,树状数组)
【BZOJ2727】双十字(动态规划,树状数组)
题面
题解
我们去年暑假的时候考试考过。
我当时写了个大暴力混了\(70\)分。。。。
大暴力是这么写的:
预处理每个位置向左右/上/下能够拓展的最多的长度(左右相当于分别求然后取\(min\))
接着枚举双十字的中轴线,所在的列
然后枚举上面那一行,枚举下面那一行。
那么,贡献显然是上面选择的左右长度\(*\)下面可以选择的左右长度\(*\)上下两行分别向上/下拓展的长度。
发现复杂度瓶颈在于枚举完上面那一行之后又去枚举下面那一行。
这个东西显然可以前缀和优化,那么每次修改都是一个区间加法,并且还是加等差数列。
线段树或者树状数组就好啦?
线段树怎么维护可以参考洛谷上那道无聊的数列
树状数组的做法,首先要知道怎么维护区间加法
核心思想是差分。
我们要加一个等差数列,如果只进行一次差分,那么就是给差分数组做区间加法。
这样显然还不行,所以我们对于差分数组再差分一次,假设得到的数组是\(c_i\),原数组是\(a_i\),差分一次的结果是\(b_i\)
那么
\sum_{i=1}^xa_i&=\sum_{i=1}^x\sum_{j=1}^ib[i]\\
&=\sum_{i=1}^x(x-i+1)b[i]\\
&=\sum_{i=1}^x(x-i+1)\sum_{j=1}^ic[i]\\
&=\sum_{i=1}^xc[i]\sum_{j=i}^x(x-j+1)\\
&=\sum_{i=1}^xc[i]\times\frac{1}{2}(n-i+2)(n-i+1)\\
&=\frac{1}{2}\sum_{i=1}^xc[i]((n^2+3n+2)-(i^2+(2n+3)i))
\end{aligned}
\]
用树状数组维护\(c[i],ic[i],i^2c[i]\)即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define RG register
#define MAX 1500000
#define MOD 1000000009
#define inv2 500000005
#define id(x,y) ((x-1)*m+y)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
bool vis[MAX];
int n,m,L[MAX],U[MAX],D[MAX],ans,K;
int c1[MAX],c2[MAX],c3[MAX];
inline int lb(int x){return x&(-x);}
void modify(int x,int w)
{
for(int i=x;i<=m;i+=lb(i))
{
add(c1[i],w);
add(c2[i],1ll*x*w%MOD);
add(c3[i],1ll*x*x%MOD*w%MOD);
}
}
int getsum(int x)
{
int s1=0,s2=0,s3=0,ret=0;
for(int i=x;i;i-=lb(i))
add(s1,c1[i]),add(s2,c2[i]),add(s3,c3[i]);
add(ret,(1ll*(x+3)*x%MOD+2)*s1%MOD);add(ret,s3);
add(ret,MOD-1ll*(x+x+3)*s2%MOD);
ret=1ll*ret*inv2%MOD;
return ret;
}
void modify(int l,int r,int w){modify(l,w);modify(r+1,MOD-w);}
void init(){for(int i=1;i<=m;++i)c1[i]=c2[i]=c3[i]=0;}
int main()
{
n=read();m=read();K=read();
for(int i=1;i<=n*m;++i)vis[i]=true;
while(K--)vis[id(read(),read())]=false;
for(int i=1;i<=n;++i)//Left
{
int s=0,now=(i-1)*m+1;
for(int j=1;j<=m;++j,++now)
{
s=vis[now]?s+1:0;
L[now]=s;
}
}
for(int i=1;i<=n;++i)//Right
{
int s=0,now=i*m;
for(int j=m;j>=1;--j,--now)
{
s=vis[now]?s+1:0;
L[now]=min(L[now],s);if(L[now])--L[now];
}
}
for(int j=1;j<=m;++j)//Up
{
int s=0,now=j;
for(int i=1;i<=n;++i,now+=m)
{
s=vis[now]?s+1:0;
U[now]=s;if(U[now])--U[now];
}
}
for(int j=1;j<=m;++j)//Down
{
int s=0,now=id(n,j);
for(int i=n;i>=1;--i,now-=m)
{
s=vis[now]?s+1:0;
D[now]=s;if(D[now])--D[now];
}
}
for(int j=2;j<m;++j,init())
for(int i=3;i<n;++i)
{
int u=id(i,j);
if(!vis[u]){init();continue;}
if(L[u])add(ans,1ll*D[u]*getsum(L[u]-1)%MOD);
modify(1,L[u-m],U[u-m]);
}
printf("%d\n",ans);
return 0;
}
【BZOJ2727】双十字(动态规划,树状数组)的更多相关文章
- 【bzoj1109】[POI2007]堆积木Klo 动态规划+树状数组
题目描述 Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体.每个积木上面都有一个数.Mary用他的所有积木垒了一个高塔.妈妈告诉Mary游戏的目的是建一个塔,使得最多的积木在正确的位置 ...
- BZOJ 2727 双十字(树状数组)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2727 题意: 思路:思路来自这里.首先对于每个位置(i,j)用C[i][j]表示该位置同 ...
- 2015 CCPC-C-The Battle of Chibi (UESTC 1217)(动态规划+树状数组)
赛后当天学长就说了树状数组,结果在一个星期后赖床时才有了一点点思路…… 因为无法提交,不确定是否正确..嗯..有错希望指出,谢谢... 嗯..已经A了..提交地址http://acm.uestc.ed ...
- BZOJ4990 [Usaco2017 Feb]Why Did the Cow Cross the Road II 动态规划 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4990 题意概括 有上下两行长度为 n 的数字序列 A 和序列 B,都是 1 到 n 的排列,若 a ...
- BZOJ4993 [Usaco2017 Feb]Why Did the Cow Cross the Road II 动态规划 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4993 题意概括 有上下两行长度为 n 的数字序列 A 和序列 B,都是 1 到 n 的排列,若 a ...
- BZOJ1264 [AHOI2006]基因匹配Match 动态规划 树状数组
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1264 题意概括 给出两个长度为5*n的序列,每个序列中,有1~n各5个. 求其最长公共子序列长度. ...
- 【BZOJ4361】isn 动态规划+树状数组+容斥
[BZOJ4361]isn Description 给出一个长度为n的序列A(A1,A2...AN).如果序列A不是非降的,你必须从中删去一个数, 这一操作,直到A非降为止.求有多少种不同的操作方案, ...
- #46 delete(动态规划+树状数组)
二维的dp非常显然,但这也没有什么优化的余地了. 注意到最后的方案中只有产生贡献的位置是有用的,剩下的部分可以在该范围内任意选取. 所以我们考虑设f[i]为i号位最后产生贡献的答案,则f[i]=max ...
- BZOJ 1264 AHOI2006 基因匹配Match 动态规划+树状数组
题目大意:给定n个数和两个长度为n*5的序列,每一个数恰好出现5次,求两个序列的LCS n<=20000.序列长度就是10W.朴素的O(n^2)一定会超时 所以我们考虑LCS的一些性质 LCS的 ...
- BZOJ3594 SCOI2014方伯伯的玉米田(动态规划+树状数组)
可以发现每次都对后缀+1是不会劣的.考虑dp:设f[i][j]为前i个数一共+1了j次时包含第i个数的LIS长度.则f[i][j]=max(f[i][j-1],f[k][l]+1) (k<i,l ...
随机推荐
- 【JUC源码解析】ThreadPoolExecutor
简介 ThreadPoolExecutor,线程池的基石. 概述 线程池,除了用HashSet承载一组线程做任务以外,还用BlockingQueue承载一组任务.corePoolSize和maximu ...
- Zigbee系列(概览)
Zigbee技术特点 低速率: 数据传输速率只有20~250kb/s, 2.4GHZ提供250kb/s, 915MHz对应40kb/s, 868Mhz对应20kb/s 低功耗:睡眠模式设备使用电池供电 ...
- scrapy-redis+selenium+webdriver 部署到linux上
背景:在使用selenium时,在本地使用windows,都会有一个图形界面,但是到了生产环境linux上没有了图形界面怎么部署呢? 解决方案: 1.安装图形化界面,不推荐,因为安装图形化界面会占用很 ...
- [leetcode-915-Partition Array into Disjoint Intervals]
Given an array A, partition it into two (contiguous) subarrays left and right so that: Every element ...
- 浅谈TSM概念、系统架构及技术发展
NFC作为一种近距离的无线通信技术,提供了一种更直接.更安全的现场交互解决方案.它能够允许电子设备之间进行非接触式点对点数据传输,实现数据交换.访问内容与服务.有了它,手机不再只是打电话.发短信以及上 ...
- Alpha阶段中间产物——GUI Prototype、WBS及PSP
作业地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/1224 内容: GUI Prototype 我的书架 我的书架→添加图书 ...
- int 和 Integer的区别
int是基本类型,默认值为0,int a=5;a只能用来计算,一般作为数值参数. Integer是引用类型,默认值为null, Integer b=5;b是一个对象,它可以有很多方法,一般做数值转换, ...
- lintcode-408-二进制求和
408-二进制求和 给定两个二进制字符串,返回他们的和(用二进制表示). 样例 a = 11 b = 1 返回 100 标签 二进制 字符串处理 脸书 思路 先相加,在处理进位,为了方便操作,将选字符 ...
- C++ auto_ptr智能指针的用法
C++中指针申请和释放内存通常采用的方式是new和delete.然而标准C++中还有一个强大的模版类就是auto_ptr,它可以在你不用的时候自动帮你释放内存.下面简单说一下用法. 用法一: std: ...
- Qt动态连接库/静态连接库创建与使用,QLibrary动态加载库
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt动态连接库/静态连接库创建与使用,QLibrary动态加载库 本文地址:https ...