[玲珑OJ1044] Quailty and Binary Operation (FFT+cdq分治)

题目链接

题意:给定两个长度为n的数组a与长度为m的数组b, 给定一个操作符op满足 x op y = x < y ? x+y : x-y.  有q个询问,每次给出询问c,问:有多少对(i, j)满足a[i] op b[j] = c ?

0 <= c <= 100000, 其余数据范围在[0, 50000].

题解:问题的关键在于如何分隔开 x < y与x >= y. cdq分治,合并的时候a[l, mid]与b[mid+1, r]卷积一次计算a[] < b[] , a[mid+1, r]与b[l, mid]再卷积一次a[] > b[]即可。

卡时,memset的时候优化了一下。

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const int N = 1e5+5;
 5 struct comp{
 6     double r,i;comp(double _r=0,double _i=0){r=_r;i=_i;}
 7     comp operator+(const comp x){return comp(r+x.r,i+x.i);}
 8     comp operator-(const comp x){return comp(r-x.r,i-x.i);}
 9     comp operator*(const comp x){return comp(r*x.r-i*x.i,r*x.i+i*x.r);}
10 }x[N<<1], y[N<<1];
11 const double pi=acos(-1.0);
12 void FFT(comp a[],int n,int t){
13     for(int i=1,j=0;i<n-1;i++){
14         for(int s=n;j^=s>>=1,~j&s;);
15         if(i<j)swap(a[i],a[j]);
16     }
17     for(int d=0;(1<<d)<n;d++){
18         int m=1<<d,m2=m<<1;
19         double o=pi/m*t;comp _w(cos(o),sin(o));
20         for(int i=0;i<n;i+=m2){
21             comp w(1,0);
22             for(int j=0;j<m;j++){
23                 comp &A=a[i+j+m],&B=a[i+j],t=w*A;
24                 A=B-t;B=B+t;w=w*_w;
25             }
26         }
27     }
28     if(t==-1)for(int i=0;i<n;i++)a[i].r/=n;
29 }
30 int a[N], b[N], n, m, q;
31 ll ans[N];
32 void cdq(int l, int r){
33     if(l == r){
34         ans[0] += a[l]*b[l];
35         return;
36     }
37     int mid = l+r >> 1;
38     cdq(l, mid);
39     int len = 1;
40     while(len <= (r-l+1)) len <<= 1;
41     memset(x, 0, sizeof(comp)*len );
42     memset(y, 0, sizeof(comp)*len );
43     for(int i = l; i <= mid; i++)
44         x[i-l] = comp(a[i], 0);
45     for(int i = mid+1; i <= r; i++)
46         y[i-mid-1] = comp(b[i], 0);
47     FFT(x, len, 1); FFT(y, len, 1);
48     for(int i = 0; i < len; i++)
49         x[i] = x[i]*y[i];
50     FFT(x, len, -1);
51     for(int i = l+mid+1; i <= mid+r; i++)
52         ans[i] += x[i-l-mid-1].r+0.5;
53     for(int i = 0; i < len; i++)
54         x[i] = y[i] = comp(0, 0);
55     for(int i = mid+1; i <= r; i++)
56         x[i-mid-1] = comp(a[i], 0);
57     for(int i = l; i <= mid; i++)
58         y[mid+1-i] = comp(b[i], 0);
59     FFT(x, len, 1); FFT(y, len, 1);
60     for(int i = 0; i < len; i++)
61         x[i] = x[i]*y[i];
62     FFT(x, len, -1);
63     for(int i = 1; i <= r-l; i++)
64         ans[i] += x[i].r+0.5;
65     cdq(mid+1, r);
66 }
67
68 int main(){
69     int t, x, maxn; scanf("%d", &t);
70     while(t--){
71         scanf("%d%d%d", &n, &m, &q);
72         maxn = 0;
73         for(int i = 0; i < n; i++){
74             scanf("%d", &x);
75             maxn = max(maxn, x);
76             a[x]++;
77         }
78         for(int i = 0; i < m; i++){
79             scanf("%d", &x);
80             maxn = max(maxn, x);
81             b[x]++;
82         }
83         cdq(0, maxn);
84         while(q--){
85             scanf("%d", &x);
86             printf("%lld\n", ans[x]);
87         }
88         memset(a, 0, sizeof(int)*(maxn+3));
89         memset(b, 0, sizeof(int)*(maxn+3));
90         memset(ans, 0, sizeof(ll)*(maxn*2+3));
91     }
92     return 0;
93 }

时间: 2024-10-11 06:44:48

[玲珑OJ1044] Quailty and Binary Operation (FFT+cdq分治)的相关文章

HDU5730 FFT+CDQ分治

题意:dp[n] = ∑ ( dp[n-i]*a[i] )+a[n], ( 1 <= i < n) cdq分治. 计算出dp[l ~ mid]后,dp[l ~ mid]与a[1 ~ r-l]做卷积运算. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 4e5+5; 4 const int mod = 313; 5 const double pi = acos(-1.0); 6 struct comp

hdu 5730 Shell Necklace fft+cdq分治

题目链接 dp[n] = sigma(a[i]*dp[n-i]), 给出a1.....an, 求dp[n]. n为1e5. 这个式子的形式显然是一个卷积, 所以可以用fft来优化一下, 但是这样也是会超时的. 所以可以用cdq分治来优化. cdq分治就是处理(l, mid)的时候, 将dp[l]...dp[mid]对dp[mid+1]...dp[r]做的贡献都算出来. #include <bits/stdc++.h> using namespace std; #define pb(x) pus

HDU 5730 Shell Necklace(CDQ分治+FFT)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3,则其权值为5,现在有长度为n的字段,求通过不同拆分得到的字段权值乘积和. [题解] 记DP[i]表示长度为i时候的答案,DP[i]=sum_{j=0}^{i-1}DP[j]w[i-j],发现是一个卷积的式子,因此运算过程可以用FFT优化,但是由于在计算过程中DP[j]是未知值,顺次计算复杂度是O(

Shell Necklace (dp递推改cdq分治 + fft)

首先读出题意,然后发现这是一道DP,我们可以获得递推式为 然后就知道,不行啊,时间复杂度为O(n2),然后又可以根据递推式看出这里面可以拆解成多项式乘法,但是即使用了fft,我们还需要做n次多项式乘法,时间复杂度又变成O(n2 * log n),显然不可以.然后又利用c分治思维吧问题进行拆分问题但是,前面求出来的结果对后面的结果会产生影响,所以我们使用cdq分治思想来解决这个问题,时间复杂度变为O(n * log2n). #include<bits/stdc++.h> using namesp

BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb.显然,两朵花可能有同样的属性.需要统计出评出每个等级的花的数量. Input 第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值. 以下N行,每

HDU5322 Hope(DP + CDQ分治 + NTT)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5322 Description Hope is a good thing, which can help you conquer obstacles in your life, just keep fighting, and solve the problem below. In mathematics, the notion of permutation relates to the ac

COGS 2479. [HZOI 2016]偏序 [CDQ分治套CDQ分治 四维偏序]

传送门 给定一个有n个元素的序列,元素编号为1~n,每个元素有三个属性a,b,c,求序列中满足i<j且ai<aj且bi<bj且ci<cj的数对(i,j)的个数. 对于100%的数据,1<=n<=50000,保证所有的ai.bi.ci分别组成三个1~n的排列. $CDQ$分治套$CDQ$分治也不是很难嘛 对于本题,设四维$a,b,c,d$ $Sort\ at\ a$ $CDQ(l,r)$ $\quad CDQ(l,mid)$ $\quad CDQ(mid+1,r)$ $\

BZOJ 2716: [Violet 3]天使玩偶 [CDQ分治]

传送门 题意: 维护二维点集P,支持以下两个操作(1)插入点(x,y)(2)给定询问(x,y),求点集中离询问点最近的点距离定义为曼哈顿距离Dis(P1,P2)=|x1-x2|+|y1-y2|n,m<=500000x,y<=1000000 时间,$x$,$y$ $CDQ$分治里需要四个象限分类讨论,树状数组维护最大值 然后有两个象限是后缀和 然后跟$PoPoQQQ$学了一个神奇的技巧,树状数组加一个时间戳,就可以不用每次清空之前的操作了 #include <iostream> #i

【BZOJ3456】【CDQ分治+FNT】城市规划

试题来源 2013中国国家集训队第二次作业 问题描述 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案. 好了, 这就是困扰阿狸的问题.