题解 P3924 【康娜的线段树】
by zcysky
出题人是个智障,这个题可能是洛谷2017年以来月赛最简单的题。
原本出题人这段时间在沉迷Angel Beats,结果他正打算写题面的时候发现了一个了不得的事实:
曾经有一位叫做jxxx_2的dalao用过Tachibana Kanade作为某种线段树的代言人……
于是题面就变成了现在泥萌看到的样子。(还挺萌的不是吗~)
30分:
您会写线段树吗?
直接模拟即可。
什么?不会写?那就把题面上的拖下来即可。
70分:
考虑期望的性质。我们发现期望具有线性性。那么每一棵子树全部被区间加之后对答案的贡献可以单独计算。于是就可以用正常的线段树打标记的做法进行维护。
复杂度:
100分:
回顾计算答案的过程,我们发现对答案产生实际贡献的点只跟叶子节点和他的深度有关。深度可以维护叶子节点的深度前缀和,这样可以
具体贡献的计算方法非常简单,如果还不清楚的可以看标程。
复杂度:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e7+5;
ll sumv[maxn<<1],a[maxn],s[maxn];
int p[maxn];
namespace io
{
const int MAXBUF = 1 << 22;
char B[MAXBUF], *S = B, *T = B;
#define getc() (S == T && (T = (S = B) + fread(B, 1, MAXBUF, stdin), S == T) ? 0 : *S++)
template<class Type> inline Type read()
{
register Type aa = 0;
register bool bb = 0;
register char ch, *S = io::S, *T = io::T;
for(ch = getc(); (ch < '0' || ch > '9') && ch != '-'; ch = getc())
;
for(ch == '-' ? bb = 1 : aa = ch - '0', ch = getc(); '0' <= ch && ch <= '9'; ch = getc())
aa = aa * 10 + ch - '0';
io::S = S, io::T = T;
return bb ? -aa : aa;
}
int (*F)() = read<int>;
template<> inline double read()
{
register double aa, bb;
register char ch;
register char *S = io::S, *T = io::T;
while(ch=getc(),(ch<'0'||ch>'9'))
;aa=ch-'0';
while(ch=getc(),(ch>='0'&&ch<='9'))aa=aa*10+ch-'0';
if(ch=='.'){bb=1;while(ch=getc(),ch>='0'&&ch<='9')bb*=0.1,aa+=bb*(ch-'0');}
io::S = S, io::T = T;
return aa;
}
char buff[MAXBUF], *iter = buff;
template<class T>inline void P(register T x, register char ch = '\n')
{
static int stack[110];
register int O = 0;
register char *iter = io::iter;
if(!x)*iter++ = '0';
else
{
(x < 0) ? x = -x, *iter++ = '-' : 1;
for(; x; x /= 10)
stack[++O] = x % 10;
for(; O; *iter++ = '0' + stack[O--])
;
}
*iter++ = ch, io::iter = iter;
}
inline void putc(register char ch) {*iter++ = ch;}
inline void ouput() {fwrite(buff, 1, iter - buff, stdout), iter = buff;}
}
#define lson o<<1
#define rson o<<1|1
int d=0;
inline void build(int l,int r,int o,int t){
if(l==r){sumv[o]=a[l];p[l]=t;d=max(d,t);return;}
int mid=l+r>>1;
build(l,mid,lson,t+1);
build(mid+1,r,rson,t+1);
sumv[o]=sumv[lson]+sumv[rson];
}
inline ll query(int l,int r,int o,int t,ll tt){
if(l==r){return 1LL*(1LL<<t)*(tt+sumv[o]);}
int mid=l+r>>1;
return query(l,mid,lson,t-1,tt+sumv[o])+query(mid+1,r,rson,t-1,tt+sumv[o]);
}
ll gcd(ll a,ll b){
while(b){
ll r=a%b;a=b;b=r;
}
return a;
}
int main(){
using io::P;
int (*F)()=io::read<int>;
int n=F(),m=F(),yyy=F();
for(register int i=1;i<=n;++i)a[i]=F();
build(1,n,1,1);
ll ans=query(1,n,1,d-1,0),y=1LL<<(d-1);
ll yy=gcd(y,yyy);yyy/=yy;y/=yy;
for(register int i=1;i<=n;++i)s[i]=s[i-1]+1LL*(((1LL<<p[i])-1)<<(d-p[i]));
while(m--){
int l=F(),r=F(),x=F();
ans+=(s[r]-s[l-1])*x;
P(ans/y*yyy);
io::ouput();
}
}