[bzoj]2962序列操作

标签: 线段树


题目链接

题意

给你一串序列,要你维护三个操作:

1.区间加法

2.区间取相反数

3.区间内任意选k个数相乘的积

题解

第三个操作看起来一脸懵逼啊。

其实是可以合并的。

$ c[o].s[i]=\sum_{j=0}^{20}c[lc].s[j]×c[rc].s[i-j]\(
跟\)C_mn=\sum_{i=0}n C_ni×C_{m-n}{n-i} $这个等式是一个道理的吧。

然后想怎么维护加和取反。

取反比较容易,把取奇数个的答案变成相反数。

加法就稍微复杂一点。

假如p是加上的数,s[i]是区间内取k个数的答案。

\[s[i]=\sum_{j=0}^k C_{n-j}^i×s[j]×p^{k-j}
\]

Code

(不知道为什么常数很大,bzoj上43s才过)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
} const int mod=19940417;
const int maxn=1e5+20;
struct node {
int s[21];
int add,rev;
void Merge(node a,node b)
{
REP(i,0,20)
{
s[i]=0;
REP(j,0,i)s[i]=(s[i]+(ll)a.s[j]*b.s[i-j])%mod;
}
}
}; node c[maxn*4]; int n;
int a[maxn],C[maxn][25]; #define lc (o<<1)
#define rc (o<<1 | 1)
#define left lc,l,mid
#define right rc,mid+1,r void Reverse(int o,int l,int r)
{
c[o].rev^=1;
c[o].add*=-1;
REP(i,0,20)
if(i & 1)c[o].s[i]*=-1;
} void Add(int o,int l,int r,ll add)
{
c[o].add=(c[o].add+add)%mod;
DREP(i,min(20,r-l+1),0)
{
ll X=add;
DREP(j,i-1,0)
{
c[o].s[i]=(c[o].s[i]+(ll)c[o].s[j]*X%mod*C[r-l+1-j][i-j])%mod;
X=(ll)X*add%mod;
}
}
} void pushdown(int o,int l,int r)
{
int mid=(l+r)>>1;
if(c[o].rev)
{
c[o].rev=0;
Reverse(lc,l,mid);
Reverse(rc,mid+1,r);
}
if(c[o].add)
{
Add(lc,l,mid,c[o].add);
Add(rc,mid+1,r,c[o].add);
c[o].add=0;
}
} void make_tree(int o,int l,int r)
{
if(l==r)
{
c[o].s[0]=1;c[o].s[1]=a[l];
c[o].add=c[o].rev=0;
return;
}
int mid=(l+r)>>1;
make_tree(left);
make_tree(right);
c[o].Merge(c[lc],c[rc]);
} int q; void init()
{
n=read();q=read();
REP(i,1,n)a[i]=read();
C[0][0]=1;
REP(i,1,n)
{
C[i][0]=1;
REP(j,1,i)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
make_tree(1,1,n);
} void updatea(int ql,int qr,ll x,int o,int l,int r)
{
if(ql<=l && r<=qr)
{
Add(o,l,r,x);
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
if(ql<=mid )updatea(ql,qr,x,left);
if(qr>mid)updatea(ql,qr,x,right);
c[o].Merge(c[lc],c[rc]);
} void updater(int ql,int qr,int o,int l,int r)
{
if(ql<=l && r<=qr)
{
Reverse(o,l,r);
return;
}
int mid=(l+r)>>1;
pushdown(o,l,r);
if(ql<=mid)updater(ql,qr,left);
if(qr>mid)updater(ql,qr,right);
c[o].Merge(c[lc],c[rc]);
} node query(int ql,int qr,int o,int l,int r)
{
if(ql<=l && r<=qr)return c[o];
int mid=(l+r)>>1;
pushdown(o,l,r);
if(ql>mid)return query(ql,qr,right);
else if(qr<=mid)return query(ql,qr,left);
else
{
node a=query(ql,mid,left),b=query(mid+1,qr,right);
node c;c.Merge(a,b);
return c;
}
} void doing()
{
REP(i,1,q)
{
char ch;
//cin>>ch;
scanf("\n%c",&ch);
if(ch=='I')
{
int l=read(),r=read();ll x=read();
updatea(l,r,x,1,1,n);
}
else if(ch=='R')
{
int l=read(),r=read();
updater(l,r,1,1,n);
}else
{
int l=read(),r=read(),k=read();
node x=query(l,r,1,1,n);
printf("%d\n",(x.s[k]+mod)%mod);
}
}
} int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
init();
doing();
return 0;
}

[bzoj]2962序列操作的更多相关文章

  1. bzoj 2962 序列操作

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 有一个长度为n的序列, ...

  2. bzoj 2962 序列操作——线段树(卷积?)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 如果 _,_,_,…… 变成了 (_+k),(_+k),(_+k),…… ,计算就是在 ...

  3. bzoj 2962 序列操作 —— 线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可: ...

  4. bzoj 1858 序列操作

    bzoj 1858 序列操作 带有随机多个区间单值覆盖的区间操作题,可考虑用珂朵莉树解决. #include<bits/stdc++.h> using namespace std; #de ...

  5. 【BZOJ-2962】序列操作 线段树 + 区间卷积

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 678  Solved: 246[Submit][Status][Discuss] ...

  6. BZOJ 2962

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 618  Solved: 225[Submit][Status][Discuss] ...

  7. bzoj2962 序列操作

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 1145  Solved: 378[Submit][Status][Discuss ...

  8. (WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作

    二次联通门 : BZOJ 1858: [Scoi2010]序列操作 /* BZOJ 1858: [Scoi2010]序列操作 已经... 没有什么好怕的的了... 16K的代码... 调个MMP啊.. ...

  9. bzoj 1858: [Scoi2010]序列操作

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MB 线段树,对于每个区间需要分别维护左右和中间的1和0连续个数,并在op=4时特殊 ...

随机推荐

  1. destoon各栏目调用汇总

    ================================================================== destoon各栏目调用汇总 ================== ...

  2. CCF系列之字符串匹配(201409-3)

    试题编号:201409-3试题名称:字符串匹配时间限制: 1.0s内存限制: 256.0MB 问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当 ...

  3. mysql数据库管理工具navicat for mysql怎么用

    mysql数据库管理工具navicat for mysql,对于不怎么喜欢图形界面或者不太方便使用SQL的时候.我们可以通过用这个图形界面数据库管理工具来管理mysql,本经验咗嚛就简单介绍一下怎么用 ...

  4. TCP三次握手机制中的seq和ack

    TCP连接的三次握手:第一次(A--->B),SYN=1,seq=x第二次(B--->A),SYN=1,ACK=1,seq=y,ack=x+1 第三次(A--->B),ACK=1,s ...

  5. maven项目使用jacoco插件检测代码覆盖率详细配置

    使用maven构建项目(java项目或者web项目都可以) jacoco插件的配置参考官方网址:http://www.eclemma.org/jacoco/trunk/doc/maven.html ( ...

  6. scrapy_xpath

    什么是xpath? 路径表达式 在xml和html中进行导航 包含标准函数库 遵循w3c标准 xpth节点关系是什么? 父节点 子节点 兄弟节点 先辈节点 后代节点 xpth语法 a         ...

  7. 控制器没有足够的带宽可利用为USB大容量存储设备的解决方法

    伴随网盘时代的没落,最近刚入手了一个移动硬盘.现在的移动硬盘都是USB3.0,传输速度比USB2.0要快很多.但是链接笔记本电脑后发现传输速度在20MB/s左右,跟USB2.0速度差不多,并不能达到传 ...

  8. [C#] 《Concurrency in C# Cookbook》读书笔记(一)- 并发编程概述

    并发编程概述 前言 我们经常在耳边听说一些关于高性能.并发和并行等名词,并且很多人都对并发编程有一些误解. 误解 1:并发就是多线程? 答:多线程只不过是并发编程的其中一种形式而已.并发编程的种类很多 ...

  9. squid安装及运行指南

    squid安装及运行指南 0. What is squid Squid是一个高性能的代理缓存服务器,Squid支持FTP.gopher.HTTPS和HTTP协议.和一般的代理缓存软件不同,Squid用 ...

  10. JS前端验证代码

    手机号码正则表达式验证: function checkPhone(){ var phone = document.getElementById('phone').value; if(!(/^1[345 ...