题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962

维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可;

取反只需要把奇数个数的乘积和变成相反数即可;

关键是区间 + k:比如对于一个元素,原来是 a, b, c,+ k 变成 (a+k), (b+k), (c+k)

从每个括号里选 a,b,c 或者 k,如果选 j 个 k ,那么就是 sum[i] += sum[i-j] * k^j * C(len-(i-j), j),组合数表示从剩余的位置中选 j 个 k;

详细可以看这个博客:https://blog.csdn.net/qq_35866453/article/details/77998472

注意一下处理 rev 标记和 lzy 标记,顺序是先 reverse 再 add,更改 rev 标记时要把 lzy 标记取反;

调了一上午:

1.各种计算 sum 时,上限原来写的是20,又觉得不好,改成 len,然而应该是 min(len,20) ...

2.query 写得不好的话会 TLE ... 还是模仿了 Narh 的写法,感觉很优秀。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
int const xn=5e4+,mod=;
int n,q,cnt=,a[xn],lzy[xn<<],ans[xn];
ll c[xn][];
bool rev[xn<<];
char ch;
struct N{int ls,rs,len; ll sum[];}t[xn<<];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
void init()
{
for(int i=;i<=n;i++)c[i][]=;
for(int i=;i<=n;i++)
for(int j=;j<=min(i,);j++)
c[i][j]=(c[i-][j]+c[i-][j-])%mod;
}
ll pls(ll a,ll b){a=a+b; while(a>=mod)a-=mod; while(a<)a+=mod; return a;}
void pushup(int x)
{
int ls=t[x].ls,rs=t[x].rs,lm=min(t[x].len,);
for(int i=;i<=lm;i++)//min!!
{
t[x].sum[i]=;
for(int j=;j<=i;j++)
t[x].sum[i]=pls(t[x].sum[i],(t[ls].sum[j]*t[rs].sum[i-j])%mod);
}
}
void ad(int x,int k)
{
int len=t[x].len,lm=min(len,);
for(int i=lm;i>=;i--)//min
for(int j=,pw=k;j<=i;j++,pw=((ll)pw*k)%mod)//
t[x].sum[i]=pls(t[x].sum[i],t[x].sum[i-j]*pw%mod*c[len-i+j][j]%mod);
lzy[x]=pls(lzy[x],k);
}
void re(int x)
{
int lm=min(t[x].len,);
for(int i=;i<=lm;i+=)t[x].sum[i]=pls(mod,-t[x].sum[i]);//min
rev[x]^=;
lzy[x]=pls(mod,-lzy[x]);
}
void pushdown(int x)
{
int ls=t[x].ls,rs=t[x].rs;
if(rev[x])re(ls),re(rs),rev[x]=;
if(lzy[x])ad(ls,lzy[x]),ad(rs,lzy[x]),lzy[x]=;
}
void build(int x,int l,int r)
{
t[x].sum[]=; t[x].len=r-l+;
if(l==r){t[x].sum[]=a[l]; return;}
t[x].ls=++cnt; t[x].rs=++cnt;
int ls=t[x].ls,rs=t[x].rs;
build(ls,l,mid); build(rs,mid+,r);
pushup(x);
}
void add(int x,int l,int r,int L,int R,int k)
{
if(l>=L&&r<=R){ad(x,k); return;}
pushdown(x);
int ls=t[x].ls,rs=t[x].rs;
if(mid>=L)add(ls,l,mid,L,R,k);
if(mid<R)add(rs,mid+,r,L,R,k);
pushup(x);
}
void reverse(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R){re(x); return;}
pushdown(x);
int ls=t[x].ls,rs=t[x].rs;
if(mid>=L)reverse(ls,l,mid,L,R);
if(mid<R)reverse(rs,mid+,r,L,R);
pushup(x);
}
/*
ll query(int x,int l,int r,int L,int R,int k)
{
int ls=t[x].ls,rs=t[x].rs;
if(l>=L&&r<=R)return t[x].sum[k];
pushdown(x);
if(mid>=R)return query(ls,l,mid,L,R,k);
else if(mid<L)return query(rs,mid+1,r,L,R,k);
else
{
ll ret=0;
for(int i=0;i<=k;i++)
ret=pls(ret,query(ls,l,mid,L,R,i)*query(rs,mid+1,r,L,R,k-i)%mod);
return ret;
}
}
*/
void query(int cr,int l,int r,int L,int R,int k)
{
if(l>=L&&r<=R)
{
int lm=min(k,r-l+);
for(int i=k;i>=;i--)
for(int j=;j<=lm&&j<=i;j++)//j<=i
ans[i]=((ll)ans[i]+t[cr].sum[j]*ans[i-j])%mod;
return;
} pushdown(cr);
if(L<=mid) query(t[cr].ls,l,mid,L,R,k);
if(mid<R) query(t[cr].rs,mid+,r,L,R,k);
} int main()
{
n=rd(); q=rd();
init();
for(int i=;i<=n;i++)a[i]=rd();
build(,,n);
ans[]=;
for(int i=,a,b,c;i<=q;i++)
{
cin>>ch;
a=rd(); b=rd();
if(ch!='R')c=rd();
if(ch=='I')c=pls(c,),add(,,n,a,b,c);
if(ch=='R')reverse(,,n,a,b);
if(ch=='Q')
// printf("%lld\n",query(1,1,n,a,b,c)%mod); {
for(int i=;i<=c;i++)ans[i]=;
query(,,n,a,b,c);
printf("%d\n",ans[c]);
} }
return ;
}

bzoj 2962 序列操作 —— 线段树的更多相关文章

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

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

  2. [bzoj]2962序列操作

    [bzoj]2962序列操作 标签: 线段树 题目链接 题意 给你一串序列,要你维护三个操作: 1.区间加法 2.区间取相反数 3.区间内任意选k个数相乘的积 题解 第三个操作看起来一脸懵逼啊. 其实 ...

  3. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

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

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

  5. bzoj 2962 序列操作

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

  6. BZOJ 1858: [Scoi2010]序列操作( 线段树 )

    略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...

  7. 【BZOJ-1858】序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1961  Solved: 991[Submit][Status ...

  8. 【bzoj1858】[Scoi2010]序列操作 线段树区间合并

    题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...

  9. 【BZOJ2962】序列操作 线段树

    [BZOJ2962]序列操作 Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反 ...

随机推荐

  1. POJ3621 Sightseeing Cows【最短路】

    题目大意:在一个无向图里找一个环,是的点权和除以边权和最大 思路:UVA11090姊妹题 事实上当这题点权和都为1时就是上一题TUT #include <stdio.h> #include ...

  2. 使用WaveOut API播放WAV音频文件(解决卡顿)

    虽然waveout已经过时,但是其api简单,有些时候也还是需要用到. 其实还是自己上msdn查阅相应api最靠谱,waveout也有提供暂停.设置音量等接口的,这里给个链接,需要的可以自己查找: h ...

  3. 线段上的格点 辗转相除法(GCD)

    /*问题描述:线段上的格点给定平面上的两个格点 P1 = (x1, y1) ; P2 = (x2, y2) 线段P1 P2上,除P1 和 P2以外一共有几个格点*//*分析过程在格点上画P1(0,5) ...

  4. CodeForces - 462B Appleman and Card Game

    是一道简单题 将字母从个数多到小排序 然后 再按题目算法得到最多 但是注意 数据类型声明 money要为long long #include <iostream> #include < ...

  5. BZOJ1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

    n<=3000个点m<=20000条无向边的图,有p<=n个出发点,每个出发点都不可拆,现拆一些点使每个出发点都不能到达点1,求最小点数. 简单的最小割.每个点拆成两个x和y,无向边 ...

  6. 内存管理(——高质量程序设计语言C/C++第16章)

    内存的分配方式: 1.静态存储区分配:全局变量,static变量等,在程序编译时已经分配了存储内存,在程序运行的整个期间一直存在 2.程序的堆栈上:程序的局部变量,包括程序的形参等,只存在于程序的运行 ...

  7. delete NULL

    面试某公司的时候,某技术主管说你这delete前没有判断指针是否为NULL,当时我就…… 看来这是个传说中的好习惯,每当delete一个指针的时候,要先判断是不是NULL.比如: if ( p != ...

  8. XCode 或者ITune 添加账号时,提示:This action could not be completed. 或者 Access Privileges

    当遇到This action could not be completed 或者 You do not have enough access privileges for this operation ...

  9. 一个开发的Linux使用心得总结

    Liunx介绍 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的UNIX工具软件.应用程序和网络协 ...

  10. 关于Android Service真正的全然具体解释,你须要知道的一切

    转载请注明出处(万分感谢! ): http://blog.csdn.net/javazejian/article/details/52709857 出自[zejian的博客]   Service全部内 ...