BZOJ4836 [Lydsy1704月赛]二元运算 分治 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8830036.html
题目传送门 - BZOJ4836
题意
定义二元运算$opt$满足
$$x\ opt\ y=\begin{cases}x+y & \text{$(x<y)$} \\ x-y & \text{$(x\geq y)$}\end{cases}$$
现在给定一个长为$n$的数列$a$和一个长为$m$的数列$b$,接下来有$q$次询问。每次询问给定一个数字$c$你需要求出有多少对$(i, j)$使得$a_i\ opt\ b_j=c$。
题解
这题看了标签差不多就是傻逼题QAQ。
标签:分治+FFT
好了题解就这么点QAQ。
居然写了半个小时还好1A不然完蛋。
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
$\vdots$
还是来正经点的吧。
首先不考虑括号里的条件,假如分别针对两种运算$x+y$和$x-y$来写,该怎么办?
$FFT$套路啊。
我们对于$a$数组搞$50001$个桶,其中下标为$i$的桶保存到就是$a_x=i$的$x$个数。
对于$b$也同理。
假装$a_i$表示原先的$a$数组中$i$的个数,$b_i$同理。
然后你要快速算$x+y$相同的,写下式子:
$$h_i=\sum_{j=0}^{i}a_jb_{i-j}$$
显然可以$FFT$优化。
然后你要算$x-y$相同的,你假装桶有负的下标,对于每一个$i$,使$b_{-i}=b_i$。
然后让$b$整体向下标的正方向移动$50000$个单位(对于有效的前$50001$个,这个操作的效果就是将原来的$50001$个桶翻转),就可以列出和原来的那个差不多的式子,同样也可以$FFT$。
但是原运算法则中有括号里面的条件啊。
我们要强力满足这个条件。
于是我们采用分治。
对数值进行分治。
我们分$3$类对最终答案进行贡献。
假装我们把区间分成了$[L,mid]$和$(mid,R]$。
$1.x=y$,只要再长度为$1$的区间内自己贡献一下就可以了。具体看代码。
$2.x<y$,那我们只要让$a[L,mid]$和$b(mid,R]$按照原式的第一种运算方式算,并$FFT$优化即可。
$3.x>y$,那我们只要让$a(mid,R]$和$b[l,mid]$按照原式的第二种运算方式算,并$FFT$优化即可。
伪代码:
solve(L,R)
if (L=R)
-->1.x=y
return
-->2.x<y
-->3.x>y
solve(L,mid),solve(mid+1,R)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1<<17;
double PI=acos(-1.0);
int read(){
int x=0;
char ch=getchar();
while (!('0'<=ch&&ch<='9'))
ch=getchar();
while ('0'<=ch&&ch<='9')
x=(x<<3)+(x<<1)+ch-48,ch=getchar();
return x;
}
int T,n,m,q,a[N],b[N];
LL tot[N];
int s,d,Rev[N];
struct C{
double r,i;
C(){}
C(double a,double b){r=a,i=b;}
C operator + (C x){return C(r+x.r,i+x.i);}
C operator - (C x){return C(r-x.r,i-x.i);}
C operator * (C x){return C(r*x.r-i*x.i,r*x.i+i*x.r);}
}w[N],A[N],B[N];
void FFT(C a[],int n){
for (int i=0;i<n;i++)
if (i<Rev[i])
swap(a[i],a[Rev[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
C tmp=w[t*j]*a[i+j+d];
a[i+j+d]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
void solve(int L,int R){
if (L==R){
tot[0]+=1LL*a[L]*b[R];
return;
}
int mid=(L+R)>>1;
//a[L]...a[mid] VS b[mid+1]...b[R]
for (s=1,d=0;s<R-L;s<<=1,d++);
for (int i=0;i<s;i++){
Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(d-1));
w[i]=C(cos(2*i*PI/s),sin(2*i*PI/s));
A[i]=B[i]=C(0,0);
}
for (int i=L;i<=mid;i++)
A[i-L]=C(a[i],0);
for (int i=mid+1;i<=R;i++)
B[i-mid-1]=C(b[i],0);
FFT(A,s),FFT(B,s);
for (int i=0;i<s;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,s);
for (int i=0;i<R-L;i++)
tot[i+L+mid+1]+=(LL)(A[i].r/s+0.5);
//a[mid+1]...a[R] VS b[L]...b[mid]
for (int i=0;i<s;i++)
A[i]=B[i]=C(0,0),w[i].i*=-1.0;
for (int i=mid+1;i<=R;i++)
A[i-mid-1]=C(a[i],0);
for (int i=L;i<=mid;i++)
B[mid-i]=C(b[i],0);
FFT(A,s),FFT(B,s);
for (int i=0;i<s;i++)
A[i]=A[i]*B[i],w[i].i*=-1.0;
FFT(A,s);
for (int i=0;i<R-L;i++)
tot[i+mid+1-mid]+=(LL)(A[i].r/s+0.5);
solve(L,mid),solve(mid+1,R);
}
int main(){
T=read();
while (T--){
n=read(),m=read(),q=read();
memset(a,0,sizeof a);
memset(b,0,sizeof b);
while (n--)
a[read()]++;
while (m--)
b[read()]++;
memset(tot,0,sizeof tot);
solve(0,50000);
while (q--)
printf("%lld\n",tot[read()]);
}
return 0;
}
BZOJ4836 [Lydsy1704月赛]二元运算 分治 多项式 FFT的更多相关文章
- BZOJ4836: [Lydsy1704月赛]二元运算
BZOJ4836: [Lydsy1704月赛]二元运算 https://lydsy.com/JudgeOnline/problem.php?id=4836 分析: 分开做,维护两个桶. 分治每次求\( ...
- bzoj 4836 [Lydsy1704月赛]二元运算 分治FFT+生成函数
[Lydsy1704月赛]二元运算 Time Limit: 8 Sec Memory Limit: 128 MBSubmit: 577 Solved: 201[Submit][Status][Di ...
- BZOJ4836: [Lydsy1704月赛]二元运算【分治FFT】【卡常(没卡过)】
Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使 ...
- BZOJ 4836: [Lydsy1704月赛]二元运算 分治FFT
Code: #include<bits/stdc++.h> #define ll long long #define maxn 500000 #define setIO(s) freope ...
- bzoj 4836: [Lydsy2017年4月月赛]二元运算 -- 分治+FFT
4836: [Lydsy2017年4月月赛]二元运算 Time Limit: 8 Sec Memory Limit: 128 MB Description 定义二元运算 opt 满足 现在给定一 ...
- 【bzoj4836】[Lydsy2017年4月月赛]二元运算 分治+FFT
题目描述 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使得 a_ ...
- CodeForces 958F3 Lightsabers (hard) 启发式合并/分治 多项式 FFT
原文链接http://www.cnblogs.com/zhouzhendong/p/8835443.html 题目传送门 - CodeForces 958F3 题意 有$n$个球,球有$m$种颜色,分 ...
- UOJ#23. 【UR #1】跳蚤国王下江南 仙人掌 Tarjan 点双 圆方树 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ23.html 题目传送门 - UOJ#23 题意 给定一个有 n 个节点的仙人掌(可能有重边). 对于所有 ...
- BZOJ3451 Tyvj1953 Normal 点分治 多项式 FFT
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3451.html 题目传送门 - BZOJ3451 题意 给定一棵有 $n$ 个节点的树,在树上随机点分 ...
随机推荐
- Nginx安全相关配置和nginx.conf中文详解
一.centos下redis安全相关 1.背景 在使用云服务器时,如果我们的redis关闭了protected-mode模式,被病毒攻击的可能会大大增加,因此我们使用redis时候,最好更改默认端口, ...
- 总线复习之SPI
SPI总线协议以ds1302为例讲解 1.1概述. 1.2根据时序图来分析. 1.3再熟读一下DS1302的数据手册和SPI总线协议的使用. 1.4结合ds1302功能实现一定的功能. 1.1概述SP ...
- POJ 3186 Treats for the Cows (动态规划)
Description FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for gi ...
- jmeter循环控制器加jdbc req结果配合组合参数遍历
jdbc请求:jdbc sampler 保存结果中三个变量名 循环控制器:xhkzq 的循环次数填写:${其中一个变量名_#} 循环控制器里面:http sampler ,前置处理器,取消c ...
- Redis(REmote DIctionary Server)基础
Redis(REmote DIctionary Server)基础 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Redis是一个开放源代码(BSD许可)的内存数据结构存储,用作数 ...
- 第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges、DBContextTransaction、TransactionScope)
一. 什么是事务 我们通俗的理解事务就是一系列操作要么全部成功.要么全部失败(不可能存在部分成功,部分失败的情况). 举一个事务在我们日常生活中的经典例子:两张银行卡(甲.乙),甲向乙转钱,整个过程需 ...
- [物理学与PDEs]第5章习题4 广义 Hookean 定律的张量的对称性
设材料是超弹性的, 并设参考构形为自然状态, 证明由线性化得到的张量 ${\bf A}=(a_{ijkl})=\sex{2\cfrac{\p \bar p_{ij}}{c_{kl}}}$ 具有以下的对 ...
- slot
本文涉及的slot有:<slot>,v-slot吗,vm.$slots,vm.$scopedSlots 废弃的使用特性:slot,slot-scope,scope(使用v-slot,2.6 ...
- Python mac安装mysqlclient的一个bug
这是一个来自mysql官方的bug,反正我是看不懂. shuais-MBP:wxapp dandyzhang$ pipenv install mysqlclient Installing mysqlc ...
- 命令框下上传到gitee
git常用命令 C:\Users\Administrator>cd www/p2p设置账号C:\Users\Administrator\www\p2p>git config --globa ...