BZOJ3490 : Pa2011 Laser Pool
与横线以及竖线的交点个数很容易求,那么只要求出横线竖线交点与运动轨迹的交点数即可。
运动轨迹可以划分成若干条贯穿边界的斜线,对于第一条和最后一条,可以用bitset暴力统计。
对于中间的部分,斜线都是完整的,可以FFT预处理。
时间复杂度$O(n\log n+\frac{nq}{32})$。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef unsigned int U;
const int N=100010,M=10010,L=262150;
int n,m,cb,ce,i,j,ab[N*2],arb[N*2],rab[N*2],rarb[N*2],g[65540];
char a[N],b[N];
struct Que{int x,y,vx,vy,t,ans;}e[M];
inline int popcount(U x){return g[x>>16]+g[x&65535];}
struct BIT{
U v[N/32+5];
void clr(){for(int i=0;i<=cb;i++)v[i]=0;}
U get(int x){return v[x>>5]>>(x&31)&1;}
void set(int x,U y){if((v[x>>5]>>(x&31)&1)^y)v[x>>5]^=1U<<(x&31);}
void shl(int x,int y){
int A=y>>5,B=y&31,C=(32-B)&31,D=x>>5,E=(D<<5)+31;
for(int i=x;i<=E;i++)set(i,get(i+y));
for(int i=D+1;i<=cb;i++){
v[i]=v[i+A]>>B;
if(C)v[i]|=v[i+A+1]<<C;
}
}
void copy(int x,int y,const BIT&p){for(int i=x;i<=y;i++)v[i]=p.v[i];}
void And(int x,int y,const BIT&p){for(int i=x;i<=y;i++)v[i]&=p.v[i];}
int count(int x,int y){
int A=x>>5,B=y>>5,C,ret=0;
if(A==B){
for(int i=x;i<=y;i++)if(v[A]>>(i&31)&1)ret++;
return ret;
}
for(int i=A+1;i<B;i++)ret+=popcount(v[i]);
C=(A<<5)+31;
for(int i=x;i<=C;i++)if(v[A]>>(i&31)&1)ret++;
C=B<<5;
for(int i=C;i<=y;i++)if(v[B]>>(i&31)&1)ret++;
return ret;
}
}bA,bB,brA,brB,tA,tB;
inline void read(int&a){
char c;bool f=0;a=0;
while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
if(c!='-')a=c-'0';else f=1;
while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
if(f)a=-a;
}
namespace FFT{
int k,j,pos[L];
const double pi=acos(-1.0);
struct comp{
double r,i;comp(double _r=0,double _i=0){r=_r,i=_i;}
comp operator+(const comp&x){return comp(r+x.r,i+x.i);}
comp operator-(const comp&x){return comp(r-x.r,i-x.i);}
comp operator*(const comp&x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
}a[L],ra[L],b[L],rb[L],c[L];
void FFT(comp a[],int n,int t){
for(int i=1;i<n;i++)if(i<pos[i])swap(a[i],a[pos[i]]);
for(int d=0;(1<<d)<n;d++){
int m=1<<d,m2=m<<1;
double o=pi*2/m2*t;comp _w(cos(o),sin(o));
for(int i=0;i<n;i+=m2){
comp w(1,0);
for(int j=0;j<m;j++){
comp&A=a[i+j+m],&B=a[i+j],t=w*A;
A=B-t;B=B+t;w=w*_w;
}
}
}
if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
}
void work(){
for(k=1;k<=n||k<=m;k<<=1);k<<=1;
j=__builtin_ctz(k)-1;
for(i=0;i<k;i++)pos[i]=pos[i>>1]>>1|((i&1)<<j);
for(i=1;i<=n;i++)a[i].r=ra[n-i+1].r=::a[i];
for(i=1;i<=m;i++)b[i].r=rb[m-i+1].r=::b[i];
FFT(a,k,1),FFT(ra,k,1),FFT(b,k,1),FFT(rb,k,1);
for(i=0;i<k;i++)c[i]=a[i]*b[i];
FFT(c,k,-1);
for(i=1;i<=n+m;i++)ab[i]=(int)(c[i].r+0.5);
for(i=0;i<k;i++)c[i]=a[i]*rb[i];
FFT(c,k,-1);
for(i=1;i<=n+m;i++)arb[i]=(int)(c[i].r+0.5);
for(i=0;i<k;i++)c[i]=ra[i]*b[i];
FFT(c,k,-1);
for(i=1;i<=n+m;i++)rab[i]=(int)(c[i].r+0.5);
for(i=0;i<k;i++)c[i]=ra[i]*rb[i];
FFT(c,k,-1);
for(i=1;i<=n+m;i++)rarb[i]=(int)(c[i].r+0.5);
}
}
namespace Solve{
bool a[N],b[N];
int sa[N],sb[N];
int cnt,idx[4][N],idy[4][N];
int tot,st[N*8],en[N*8],v[N*8],pos[N*8],cur,q[N*8],sw[N*8];long long sl[N*8];
struct E{int sx,sy,ex,ey,len,w,d,nxt;}f[N*8];
inline bool check(int x,int y){return b[x]&&a[y];}
inline int abs(int x){return x>0?x:-x;}
inline int&getid(int x,int y,int d){
if(y==1||y==n)return idx[d][x];
return idy[d][y];
}
inline void makerev(int x){
f[x].sx=f[x-1].ex;
f[x].sy=f[x-1].ey;
f[x].ex=f[x-1].sx;
f[x].ey=f[x-1].sy;
f[x].w=f[x-1].w;
f[x].d=(f[x-1].d+2)&3;
}
inline int getnxt(int x,int y,int d){
if(d==0){
if(x<m&&y==n)return getid(x,y,(d+1)&3);
if(y==n)return getid(x,y,(d+2)&3);
return getid(x,y,(d+3)&3);
}
if(d==2){
if(x>1&&y==1)return getid(x,y,(d+1)&3);
if(y==1)return getid(x,y,(d+2)&3);
return getid(x,y,(d+3)&3);
}
if(d==1){
if(x<m&&y==1)return getid(x,y,(d+3)&3);
if(y==1)return getid(x,y,(d+2)&3);
return getid(x,y,(d+1)&3);
}
if(x>1&&y==n)return getid(x,y,(d+3)&3);
if(y==n)return getid(x,y,(d+2)&3);
return getid(x,y,(d+1)&3);
}
inline int cal(int x,int t,int n,int*s){
if(x+t<=n)return s[x+t]-s[x-1];
t-=n-x;
int ret=s[n-1]-s[x-1];
ret+=t/(n+n-2)*(s[n]+s[n-1]-s[1]);
t%=n+n-2;
if(t<n)return ret+s[n]-s[n-t-1];
return ret+s[n]-s[1]+s[t-n+2];
}
inline int search(int L,int r,int x){
int l=L,t=L-1,mid;
while(l<=r)if(sl[mid=(l+r)>>1]-sl[L-1]<=x)l=(t=mid)+1;else r=mid-1;
return t;
}
inline void ask(int x,int y,int t,int p){
int&ans=e[p].ans;
ans=cal(x,t,m,sb)+cal(y,t,n,sa);
int ex=m,ey=y-x+m;
if(ey>n)ey=n,ex=x-y+n;
int d=ex-x;
if(t<=d){
tA.copy(y>>5,cb,bA);
tB.copy(x>>5,cb,bB);
tB.shl(0,x);
tA.shl(0,y);
tA.And(0,t>>5,tB);
ans-=tA.count(0,t);
return;
}
if(d){
tA.copy(y>>5,cb,bA);
tB.copy(x>>5,cb,bB);
tB.shl(0,x);
tA.shl(0,y);
tA.And(0,(d-1)>>5,tB);
ans-=tA.count(0,d-1);
}
t-=d;
int o=getnxt(ex,ey,0);
int l=st[v[o]],r=en[v[o]];
o=pos[o];
int u=search(o,r,t);
ans-=sw[u]-sw[o-1];
t-=sl[u]-sl[o-1];
o=u+1;
if(o>r){
ans-=t/(sl[r]-sl[l-1])*(sw[r]-sw[l-1]);
t%=sl[r]-sl[l-1];
u=search(l,r,t);
ans-=sw[u]-sw[l-1];
t-=sl[u]-sl[l-1];
o=u+1;
}
o=q[o];
x=f[o].sx,y=f[o].sy;
if(f[o].d==0){
tA.copy(y>>5,cb,bA);
tB.copy(x>>5,cb,bB);
}
if(f[o].d==1){
y=n-y+1;
tA.copy(y>>5,cb,brA);
tB.copy(x>>5,cb,bB);
}
if(f[o].d==2){
x=m-x+1;
y=n-y+1;
tA.copy(y>>5,cb,brA);
tB.copy(x>>5,cb,brB);
}
if(f[o].d==3){
x=m-x+1;
tA.copy(y>>5,cb,bA);
tB.copy(x>>5,cb,brB);
}
tB.shl(0,x);
tA.shl(0,y);
tA.And(0,t>>5,tB);
ans-=tA.count(0,t);
}
void work(int*A,int*B){
for(i=1;i<=n;i++)sa[i]=sa[i-1]+a[i],bA.set(i,a[i]),brA.set(n-i+1,a[i]);
for(i=1;i<=m;i++)sb[i]=sb[i-1]+b[i],bB.set(i,b[i]),brB.set(m-i+1,b[i]);
cnt=0;
for(i=1;i<m;i++){
cnt++;
f[cnt].sx=i,f[cnt].sy=1;
f[cnt].ex=m,f[cnt].ey=m-i+1;
if(f[cnt].ey>n)f[cnt].ey=n,f[cnt].ex=n-1+i;
f[cnt].w=B[m-i+2];
f[cnt].d=0;
makerev(++cnt);
}
for(i=2;i<n;i++){
cnt++;
f[cnt].sx=1,f[cnt].sy=i;
f[cnt].ex=m,f[cnt].ey=m-1+i;
if(f[cnt].ey>n)f[cnt].ey=n,f[cnt].ex=n-i+1;
f[cnt].w=B[m+i];
f[cnt].d=0;
makerev(++cnt);
}
for(i=2;i<=m;i++){
cnt++;
f[cnt].sx=i,f[cnt].sy=1;
f[cnt].ex=1,f[cnt].ey=i;
if(f[cnt].ey>n)f[cnt].ey=n,f[cnt].ex=i+1-n;
f[cnt].w=A[i+1];
f[cnt].d=3;
makerev(++cnt);
}
for(i=2;i<n;i++){
cnt++;
f[cnt].sx=m,f[cnt].sy=i;
f[cnt].ex=1,f[cnt].ey=m+i-1;
if(f[cnt].ey>n)f[cnt].ey=n,f[cnt].ex=m+i-n;
f[cnt].w=A[i+m];
f[cnt].d=3;
makerev(++cnt);
}
for(i=1;i<=cnt;i++){
f[i].len=abs(f[i].sx-f[i].ex);
f[i].w-=check(f[i].ex,f[i].ey);
getid(f[i].sx,f[i].sy,f[i].d)=i;
}
for(i=1;i<=cnt;i++)f[i].nxt=getnxt(f[i].ex,f[i].ey,f[i].d);
cur=tot=0;
for(i=1;i<=cnt;i++)v[i]=0;
for(i=1;i<=cnt;i++)if(!v[i]){
st[++tot]=cur+1;
for(j=i;!v[j];j=f[j].nxt)v[q[++cur]=j]=tot;
en[tot]=cur;
}
for(i=1;i<=cnt;i++)sl[i]=sl[i-1]+f[q[i]].len,sw[i]=sw[i-1]+f[q[i]].w,pos[q[i]]=i;
}
}
int main(){
for(i=1;i<65536;i++)g[i]=g[i>>1]+(i&1);
read(n),read(m);
scanf("%s%s",a+1,b+1);
for(i=1;i<=n;i++)a[i]-='0';
for(i=1;i<=m;i++)b[i]-='0';
read(ce);
for(i=1;i<=ce;i++)read(e[i].x),read(e[i].y),read(e[i].vx),read(e[i].vy),read(e[i].t);
FFT::work();
cb=(n>m?n:m)>>5;
for(i=1;i<=n;i++)Solve::a[i]=a[i];
for(i=1;i<=m;i++)Solve::b[i]=b[i];
Solve::work(ab,arb);
for(i=1;i<=ce;i++)if(e[i].vx==1&&e[i].vy==1)Solve::ask(e[i].x,e[i].y,e[i].t,i);
for(i=1;i<=n;i++)Solve::a[i]=a[n-i+1];
for(i=1;i<=m;i++)Solve::b[i]=b[i];
Solve::work(rab,rarb);
for(i=1;i<=ce;i++)if(e[i].vx==1&&e[i].vy==-1)Solve::ask(e[i].x,n-e[i].y+1,e[i].t,i);
for(i=1;i<=n;i++)Solve::a[i]=a[i];
for(i=1;i<=m;i++)Solve::b[i]=b[m-i+1];
Solve::work(arb,ab);
for(i=1;i<=ce;i++)if(e[i].vx==-1&&e[i].vy==1)Solve::ask(m-e[i].x+1,e[i].y,e[i].t,i);
for(i=1;i<=n;i++)Solve::a[i]=a[n-i+1];
for(i=1;i<=m;i++)Solve::b[i]=b[m-i+1];
Solve::work(rarb,rab);
for(i=1;i<=ce;i++)if(e[i].vx==-1&&e[i].vy==-1)Solve::ask(m-e[i].x+1,n-e[i].y+1,e[i].t,i);
for(i=1;i<=ce;i++)printf("%d\n",e[i].ans);
return 0;
}
BZOJ3490 : Pa2011 Laser Pool的更多相关文章
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 添加 Pool Member - 每天5分钟玩转 OpenStack(123)
我们已经有了 Load Balance Pool "web servers"和 VIP,接下来需要往 Pool 里添加 member 并学习如何使用 cloud image. 先准 ...
- 创建 Pool & VIP - 每天5分钟玩转 OpenStack(122)
上节完成了 LBaaS 配置,今天我们开始实现如下 LBaaS 环境. 环境描述如下: 1. 创建一个 Pool “web servers”. 2. 两个 pool member “WEB1” 和 “ ...
- [转载】——故障排除:Shared Pool优化和Library Cache Latch冲突优化 (文档 ID 1523934.1)
原文链接:https://support.oracle.com/epmos/faces/DocumentDisplay?_adf.ctrlstate=23w4l35u5_4&id=152393 ...
- Ceph RGW 创建默认的pool
使用Ceph-deploy完成RGW服务部署后(最好是在部署RGW服务前建立如下这些pool),使用sudo ceph osd lspools 命令,会发现RGW自动以默认参数创建了N个rgw相关的p ...
- golang 裸写一个pool池控制协程的大小
这几天深入的研究了一下golang 的协程,读了一个好文 http://mp.weixin.qq.com/s?__biz=MjM5OTcxMzE0MQ==&mid=2653369770& ...
- 如何在Windows 2003+IIS6的环境下找回应用程序池(application pool)中的服务账号密码
上一篇文章说了说如何在Win2008+iis7中取出SharePoint管理账号密码的方法. 整个过程简单的讲,就是通过使用要找回密码的账号用来在SharePoint中创建一个临时的Web Appli ...
- 备忘-Sql server Timeout expired 超时时间已到. 达到了最大池大小 错误及Max Pool Size设置
select * from sysprocesses where dbid= db_id('数据库名') 通过此语句可查看目前所有的连接进程 不够了就必须设置Max Pool Size,理论最大值为3 ...
- SQL Server 2014新特性探秘(2)-SSD Buffer Pool Extension
简介 SQL Server 2014中另一个非常好的功能是,可以将SSD虚拟成内存的一部分,来供SQL Server数据页缓冲区使用.通过使用SSD来扩展Buffer-Pool,可以使得大量随 ...
随机推荐
- IDEA创建第一个项目详细过程
- tensorflow:验证码的识别(中)
三.训练识别模型 首先先拷贝一个nets文件夹,主要使用的是文件夹下的两个文件nets_factory.py.alexnet.py,用于导入训练使用的网络alexnet. nets_factory.p ...
- python 通用装饰器,带有参数的装饰器,
# 使用装饰器对有返回值的函数进行装饰# def func(functionName): # print('---func-1----') # def func_in(): # print(" ...
- ubuntu16.04安装skype
ubuntu16.04安装skype 一句命令搞定 wget https://repo.skype.com/latest/skypeforlinux-64.deb && sudo dp ...
- exec函数族
进程程序替换 进程程序替换原理 fork创建子进程执行的是和父进程相同的程序(也有可能是某个分支),通常fork出的子进程是为了完成父进程所分配的任务,所以子进程通常会调用一种exec函数(六种中的任 ...
- .Net页面缓存OutPutCache详解
一 它在Web.Config中的位置 <system.web> <!--页面缓存--> <caching> <outputCacheSettings> ...
- XAML绑定到资源文件字符串时失败
参考:https://stackoverflow.com/questions/19586401/error-in-binding-resource-string-with-a-view-in-wpf ...
- .Net开源网络爬虫Abot介绍(转)
转载地址:http://www.cnblogs.com/JustRun1983/p/abot-crawler.html .Net中也有很多很多开源的爬虫工具,abot就是其中之一.Abot是一个开源的 ...
- 【bzoj3589】动态树 树链剖分+树链的并
题解: 树链剖分是显然的 问题在于求树链的并 比较简单的方法是 用线段树打标记覆盖,查询标记区间大小 Qlog^2n 代码: #include <bits/stdc++.h> using ...
- 通过ping命令查看服务器是linux还是windows系列
通过ping命令识别服务器类型