题意:

给定长度为\(L\),元素总和为\(S\)的非负整数序列\(A\),对于每一个\(1 \leq i \leq S\),求出:所有满足\(\sum_{j=l}^rA_j=i\)的二元组\((l,r)\)排序后的中位数。

二元组的比较方式:先比较\(l\),小的在先;\(l\)相同比较\(r\),小的在先。

\(1 \leq L , S \leq 30000\)

思路:

易见可以把二元组\((l,r)\)看作一个左端点落在\(l-1\)与\(l\)之间,右端点落在\(r\)与\(r+1\)之间的区间。

那么若连续\(c\)个零的下标为\(i\)到\(i+c-1\),则一个区间的左/右端点落在\(i-1\)与\(i\)之间,或\(i\)与\(i+1\)之间,……,或\(i+c-1\)到\(i+c\)之间,不影响其总和。那么,我们可以把这\(c+1\)个落点合并为一个(不妨用\(i-1\)和\(i\)之间的那个来代表),并给它标上权值\(c+1\),意味着如果一个区间选取它为端点,就会产生另外\(c\)个与之相同的区间。

同样的,我们把一个非零元素\(a\)拆成\(a-1\)个权值为0的落点和随后紧邻的1个权值为1的落点。可以认为,任何区间都不能以权值为0的落点作为端点。

来自不同元素的落点,按照原先元素的顺序排列。

这样做的意义在于,经过变换之后,区间\([i,j]\)(其中\(i\)和\(j\)是变换之后落点的编号)在序列\(A\)的总和为\(j-i\),且共有\(m_i \cdot m_j\)个与之完全相同的区间,其中\(m_i\)是落点\(i\)的权值。

hint:对于零元素落点的合并操作,注意到\(i-1\)与\(i\)之间的落点,实际上就是前一个非零元素拆成的最后一个落点,所以合并时直接执行\(m_{last}\)+=\(c\)即可。

看到这里,有没有嗅到一股法法塔的气息!!!

对\(m\)序列求得卷积序列\(cnt\),满足:

\[cnt_i=\sum_{j-k=i}m_j \cdot m_k
\]

而\(cnt_i\)就是\(A\)数组中总和为\(i\)的连续子序列数量!

这样可以求出对每一个\(i\),二元组\((l,r)\)的数量,进而可以知道(对每一个\(i\))二元组排序后中位数的下标。

知道下标之后,就是常规操作了。注意到如果把\(m\)与自己的一个前缀做卷积,得到的\(cnt_i\),就是\(A\)中总和为\(i\),且左端点下标不超过\(k\)的区间数量,这里的\(k\)是与\(m\)前缀的长度正相关的一个值。

对于每一个\(i\),可以对所求二元组的左端点二分答案,并每次用前缀卷积得到的\(cnt_i\)判断。但是直接暴力做会超时,整体二分又用不了(单轮check的复杂度只与\(L\)相关,不满足使用整体二分的条件),所以考虑分块。

把\(m\)序列分成大小为\(\sqrt[2]{L \cdot \log L}\)的块,并通过\(O(\sqrt[2]{\frac{L}{\log L}})\)次卷积,确定对每一个\(i\),其所求二元组的\(l\)在哪一块里。

最后对每一个\(i\),在块内暴力找到准确的左端点和右端点即可。记得把\(m\)序列中的下标映射回到\(A\)序列中去。

复杂度\(O(L \cdot \sqrt[2]{L \cdot \log L})\)。

代码:

#include<iostream>
#include<cstdio>
#include<ctime>
#include<vector>
#include<cstring>
using namespace std;
#define iinf 2000000000
#define linf 1000000000000000000LL
#define ulinf 10000000000000000000ull
#define MOD1 1000000007LL
#define mpr make_pair
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned long UL;
typedef unsigned short US;
typedef pair < int , int > pii;
clock_t __stt;
inline void TStart(){__stt=clock();}
inline void TReport(){printf("\nCurrent Case Taken Time : %.3lf sec\n",(double)(clock()-__stt)/CLOCKS_PER_SEC);}
template < typename T > T MIN(T a,T b){return a<b?a:b;}
template < typename T > T MAX(T a,T b){return a>b?a:b;}
template < typename T > T ABS(T a){return a>0?a:(-a);}
template < typename T > void UMIN(T &a,T b){if(b<a) a=b;}
template < typename T > void UMAX(T &a,T b){if(b>a) a=b;}
const LL MODG=998244353,G=3;
int powM(int num,int pw,LL moD=MODG){
int ret=1;
while(pw){
if(pw&1) ret=((LL)ret*(LL)num)%moD;
num=((LL)num*(LL)num)%moD;
pw>>=1;
}
return (int)ret;
}
int n,s,rk[30005],lv[30005],a[30005],v[60005],ln,ld[60005],pcnt[60005],cnt[140005],A[140005],B[140005];
int SZ,SZINV,BUC;
void ntt(int *a,int l,bool r){
int i,j=l/2,k;
for(i=1;i<l;++i){
if(i<j) swap(a[i],a[j]);
for(k=l/2;j&k;k>>=1) j^=k;
j^=k;
}
for(i=1;(1<<i)<=l;++i){
int cl=(1<<i);
int w=powM(G,(MODG-1)/cl);
if(r) w=powM(w,MODG-2);
for(j=0;j*cl<l;++j){
int cur=1;
for(k=0;k<(cl>>1);k++){
int v1=a[j*cl+k],v2=((LL)a[j*cl+k+(cl>>1)]*(LL)cur)%MODG;
a[j*cl+k]=(v1+v2)%MODG;
a[j*cl+k+(cl>>1)]=(v1-v2+MODG)%MODG;
cur=((LL)cur*(LL)w)%(LL)MODG;
}
}
}
}
void getcnt(int pre){
int i,j,k;
memset(A,0,sizeof(int)*(SZ+5));
memset(B,0,sizeof(int)*(SZ+5));
memset(cnt,0,sizeof(int)*(SZ+5));
for(i=0;i<ln;++i){
A[i]=v[i];
}
ntt(A,SZ,0);
for(i=0;i<pre;++i){
B[ln-1-i]=v[i];
}
ntt(B,SZ,0);
for(i=0;i<SZ;++i){
A[i]=((LL)A[i]*(LL)B[i])%MODG;
}
ntt(A,SZ,1);
for(i=0;i<SZ;++i){
if(i+1-ln>=0){
cnt[i+1-ln]=((LL)A[i]*(LL)SZINV)%MODG;
}
}
}
void solve(){
// inputting start
// 数据结构记得初始化! n,m别写反!
int i,j,k;
scanf("%d",&n);
s=0;
for(i=0;i<n;++i){
scanf("%d",a+i);
s+=a[i];
}
#ifdef LOCAL
TStart();
#endif
// calculation start
// 数据结构记得初始化! n,m别写反!
ln=v[0]=1;
ld[0]=-1;
for(i=0;i<n;++i){
if(a[i]>0){
for(j=0;j<a[i]-1;++j){
ld[ln]=i;
v[ln++]=0;
}
ld[ln]=i;
v[ln++]=1;
}
else{
for(j=i;j<n && a[j]==0;++j) ++v[ln-1];
i=j-1;
}
}
for(BUC=2;BUC*BUC<ln*60;++BUC);
for(SZ=4;SZ<ln*2;SZ<<=1);
SZINV=powM(SZ,MODG-2);
getcnt(ln);
for(i=1;i<=s;++i){
rk[i]=(cnt[i]+1)/2-1;
lv[j]=-1;
}
for(i=0;i<=ln;i+=BUC){
getcnt(i);
for(j=1;j<=s;++j){
if(cnt[j]<=rk[j])
lv[j]=i;
else if(lv[j]==i-BUC)
rk[j]-=pcnt[j];
}
memcpy(pcnt,cnt,sizeof(int)*(s+3));
}
LL resL=0,resR=0;
for(i=s;i>=1;--i){
while(rk[i]>=v[lv[i]+i]*v[lv[i]]){
rk[i]-=v[lv[i]+i]*v[lv[i]];
++lv[i];
}
if(rk[i]>=0) resL+=(LL)(ld[lv[i]]+2+rk[i]/v[lv[i]+i]);
if(rk[i]>=0) resR+=(LL)(ld[lv[i]+i]+rk[i]%v[lv[i]+i]+1);
resL=(resL*233LL)%MOD1;
resR=(resR*233LL)%MOD1;
}
printf("%d %d\n",(int)resL,(int)resR);
#ifdef LOCAL
TReport();
#endif
}
int main(){
int t;
scanf("%d",&t);
while(t--){
solve();
}
return 0;
}

HDU 5530:Pipes Selection的更多相关文章

  1. Eclipse出现错误:The selection cannot be launched,and there are no recent launches

    刚装了eclipse,想写个Java程序测试一下能不能用,结果一run就出现错误,Debug也是同样的错误,错误内容为:the selection cannot be launched,and the ...

  2. HDU - 6409:没有兄弟的舞会(数学+思维)

    链接:HDU - 6409:没有兄弟的舞会 题意: 题解: 求出最大的 l[i] 的最大值 L 和 r[i] 的最大值 R,那么 h 一定在 [L, R] 中.枚举每一个最大值,那么每一个区间的对于答 ...

  3. POJ 3321:Apple Tree + HDU 3887:Counting Offspring(DFS序+树状数组)

    http://poj.org/problem?id=3321 http://acm.hdu.edu.cn/showproblem.php?pid=3887 POJ 3321: 题意:给出一棵根节点为1 ...

  4. 组件化思路:以selection为例子,使用prop-types实现组件化控制,重用

    需求 书接上文,UI 积累之select section 这里又来两个需求了. 当我点击选择了option后,我应该看到的是我选择的option的内容 多例重用,即同样是个selection,我只是需 ...

  5. HDU 2732:Leapin' Lizards(最大流)

    http://acm.hdu.edu.cn/showproblem.php?pid=2732 题意:给出两个地图,蜥蜴从一个柱子跳跃到另外一个地方,那么这个柱子就可能会坍塌,第一个地图是柱子可以容忍跳 ...

  6. HDU 4289:Control(最小割)

    http://acm.hdu.edu.cn/showproblem.php?pid=4289 题意:有n个城市,m条无向边,小偷要从s点开始逃到d点,在每个城市安放监控的花费是sa[i],问最小花费可 ...

  7. HDU 3605:Escape(最大流+状态压缩)

    http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意:有n个人要去到m个星球上,这n个人每个人对m个星球有一个选择,即愿不愿意去,"Y" ...

  8. HDU 4292:Food(最大流)

    http://acm.hdu.edu.cn/showproblem.php?pid=4292 题意:和奶牛一题差不多,只不过每种食物可以有多种. 思路:因为食物多种,所以源点和汇点的容量要改下.还有D ...

  9. 矩阵乘法 --- hdu 4920 : Matrix multiplication

    Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

随机推荐

  1. Windows装系统

    这几天电脑频繁崩溃,自己尝试着装了几次系统,遇到一些问题.有的解决了,有的没解决.将其一一记录在这里,作为经验参考. 自己以前最常用的方式是直接通过ultraiso将IOS文件解压到到U盘,会将U盘做 ...

  2. 【Spring实战】—— 4 Spring中bean的init和destroy方法讲解

    本篇文章主要介绍了在spring中通过配置init-method和destroy-method方法来实现Bean的初始化和销毁时附加的操作. 在java中,我们并不需要去管理内存或者变量,而在C或C+ ...

  3. static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

    查看HashMap源码,发现这个static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  值为16. 这个是位移算法. 例如: 4<& ...

  4. Scrum _GoodJob

    作为长大的大三老腊肉,我们已经在长大生活了两年多,对于什么是长大人最想完善的校园需求.最想拥有的校园服务媒介也有了更加深切的体会. 于是,GoodJob小团队blingbling闪现啦!! GoodJ ...

  5. 同时开左右两个SAPGUI编辑器显示同一段ABAP代码

    很多文本编辑器都支持同时开左右两个窗口显示同一段代码,使用场景可能是比较同一段代码的不同版本差异,或者是ABAP里,同一段代码在Netweaver不同版本里的实现差异,比如版本为SP1的系统A和版本为 ...

  6. bzoj2003 [Hnoi2010]矩阵

    Description Input 第一行包含三个正整数N M P表示矩阵的行数列数以及每个数的范围,接下来N行每行包含M个非负整数,其中第i行第j个数表示以格子(i,j)为右下角的2*2子矩阵中的数 ...

  7. WIN7系统 64位出现 Net Framework 数据提供程序要求 Microsoft Data Access Components(MDAC).

    WIN7系统 64位出现  Net Framework 数据提供程序要求 Microsoft Data Access Components(MDAC).请安装 Microsoft Data Acces ...

  8. bzoj 2434 [Noi2011]阿狸的打字机——AC自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2434 dfs AC自动机,走过的点权值+1,回溯的时候权值-1:走到询问的 y 串的节点,看 ...

  9. 【洛谷P2324】[SCOI2005]骑士精神

    骑士精神 题目链接 #include<iostream> #include<cstdio> using namespace std; int t,MAXD,sx,sy; ][] ...

  10. Android学习笔记_2_发送短信

    1.首先需要在AndroidManifest.xml文件中加入发送短信的权限 <uses-permission android:name="android.permission.SEN ...