BZOJ5291 BJOI2018链上二次求和(线段树)
用线段树对每种长度的区间维护权值和。
考虑区间[l,r]+1对长度为k的区间的贡献,显然其为Σk-max(0,k-i)-max(0,k-(n-i+1)) (i=l~r)。
大力展开讨论。首先变成Σk-Σmax(0,k-i)-Σmax(0,k-(n-i+1)) (i=l~r)。
第一部分是一个常数,线段树上是加了一个等差数列。打上标记即可。
后面两部分本质相同,现考虑Σmax(0,k-i) (i=l~r)。去掉max,即Σk-i (i=l~min(r,k))。根据r和k的大小关系讨论。若r<=k,线段树上加了一个一次函数;若r>k,线段树上加了一个二次函数。三种标记即可。
常数巨大,下传标记时判一下是否有标记需要传可以快至少一倍。读入序列直接当做修改就能跑过。
- #include<iostream>
- #include<cstdio>
- #include<cmath>
- #include<cstdlib>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- #define ll long long
- #define N 200010
- #define P 1000000007
- #define inv 500000004
- char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
- int gcd(int n,int m){return m==?n:gcd(m,n%m);}
- int read()
- {
- int x=,f=;char c=getchar();
- while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
- while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
- return x*f;
- }
- int n,m,a[N],s[][N];
- struct data{int l,r,sum,lazy[];
- }tree[N<<];
- inline void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
- inline void up(int k){tree[k].sum=tree[k<<].sum+tree[k<<|].sum;if (tree[k].sum>=P) tree[k].sum-=P;}
- inline void update(int k,int x,int op)
- {
- inc(tree[k].sum,1ll*x*(s[op][tree[k].r]-s[op][tree[k].l-]+P)%P);
- inc(tree[k].lazy[op],x);
- }
- inline void down(int k,int i)
- {
- update(k<<,tree[k].lazy[i],i),
- update(k<<|,tree[k].lazy[i],i),
- tree[k].lazy[i]=;
- }
- void build(int k,int l,int r)
- {
- tree[k].l=l,tree[k].r=r;
- if (l==r) return;
- int mid=l+r>>;
- build(k<<,l,mid);
- build(k<<|,mid+,r);
- }
- void add(int k,int l,int r,int x,int op)
- {
- if (l>r) return;
- if (tree[k].l==l&&tree[k].r==r) {update(k,x,op);return;}
- if (tree[k].lazy[]) down(k,);
- if (tree[k].lazy[]) down(k,);
- if (tree[k].lazy[]) down(k,);
- int mid=tree[k].l+tree[k].r>>;
- if (r<=mid) add(k<<,l,r,x,op);
- else if (l>mid) add(k<<|,l,r,x,op);
- else add(k<<,l,mid,x,op),add(k<<|,mid+,r,x,op);
- up(k);
- }
- int query(int k,int l,int r)
- {
- if (tree[k].l==l&&tree[k].r==r) return tree[k].sum;
- if (tree[k].lazy[]) down(k,);
- if (tree[k].lazy[]) down(k,);
- if (tree[k].lazy[]) down(k,);
- int mid=tree[k].l+tree[k].r>>;
- if (r<=mid) return query(k<<,l,r);
- else if (l>mid) return query(k<<|,l,r);
- else return (query(k<<,l,mid)+query(k<<|,mid+,r))%P;
- }
- void modify(int l,int r,int x)
- {
- add(,r,n,1ll*(r-l+)*x%P,),add(,r,n,P-1ll*(s[][r]-s[][l-]+P)*x%P,);
- add(,l,r-,1ll*x*inv%P,),add(,l,r-,1ll*x*(P+-l-inv)%P,),add(,l,r-,1ll*l*(l-)%P*inv%P*x%P,);
- }
- void change(int l,int r,int x)
- {
- add(,,n,1ll*(r-l+)*x%P,);
- modify(l,r,P-x),modify(n-r+,n-l+,P-x);
- }
- int main()
- {
- #ifndef ONLINE_JUDGE
- freopen("bzoj5291.in","r",stdin);
- freopen("bzoj5291.out","w",stdout);
- const char LL[]="%I64d\n";
- #else
- const char LL[]="%lld\n";
- #endif
- n=read(),m=read();
- build(,,n);
- for (int i=;i<=n;i++) s[][i]=s[][i-]+,s[][i]=(s[][i-]+i)%P,s[][i]=(s[][i-]+1ll*i*i)%P;
- for (int i=;i<=n;i++) change(i,i,read());
- while (m--)
- {
- int op=read();
- if (op==)
- {
- int l=read(),r=read(),x=read();
- if (l>r) swap(l,r);
- change(l,r,x);
- }
- else
- {
- int l=read(),r=read();
- printf("%d\n",query(,l,r));
- }
- }
- return ;
- }
BZOJ5291 BJOI2018链上二次求和(线段树)的更多相关文章
- [BZOJ5291][BJOI2018]链上二次求和(线段树)
感觉自己做的麻烦了,但常数似乎不算差.(只是Luogu最慢的点不到2s本地要跑10+s) 感觉我的想法是最自然的,但不明白为什么网上似乎找不到这种做法.(不过当然所有的做法都是分类大讨论,而我的方法手 ...
- BZOJ5291/洛谷P4458/LOJ#2512 [Bjoi2018]链上二次求和 线段树
原文链接http://www.cnblogs.com/zhouzhendong/p/9031130.html 题目传送门 - LOJ#2512 题目传送门 - 洛谷P4458 题目传送门 - BZOJ ...
- 2018.01.04 bzoj5291: [Bjoi2018]链上二次求和(线段树)
传送门 线段树基础题. 题意:给出一个序列,要求支持区间加,查询序列中所有满足区间长度在[L,R][L,R][L,R]之间的区间的权值之和(区间的权值即区间内所有数的和). 想题555分钟,写题202 ...
- 【BZOJ5291】[BJOI2018]链上二次求和(线段树)
[BZOJ5291][BJOI2018]链上二次求和(线段树) 题面 BZOJ 洛谷 题解 考虑一次询问\([l,r]\)的答案.其中\(S\)表示前缀和 \(\displaystyle \sum_{ ...
- bzoj 5291: [Bjoi2018]链上二次求和
Description 有一条长度为n的链(1≤i<n,点i与点i+1之间有一条边的无向图),每个点有一个整数权值,第i个点的权值是 a_i.现在有m个操作,每个操作如下: 操作1(修改):给定 ...
- 洛谷P4458 /loj#2512.[BJOI2018]链上二次求和(线段树)
题面 传送门(loj) 传送门(洛谷) 题解 我果然是人傻常数大的典型啊-- 题解在这儿 //minamoto #include<bits/stdc++.h> #define R regi ...
- loj2512 [BJOI2018]链上二次求和
传送门 分析 咕咕咕 代码 #include<iostream> #include<cstdio> #include<cstring> #include<st ...
- 「BJOI2018」链上二次求和
「BJOI2018」链上二次求和 https://loj.ac/problem/2512 我说今天上午写博客吧.怕自己写一上午,就决定先写道题. 然后我就调了一上午线段树. 花了2h找到lazy标记没 ...
- [bzoj5291]链上二次求和
记$bi=b_{i-1}+ai$,$ci=c_{i-1}+bi$,那么答案就是$\sum_{i=l}^{r}\sum_{j=0}^{n-i}b_{j+i}-bj=(r-l+1)cn-\sum_{i=l ...
随机推荐
- 改革春风吹满地,安卓新系统Q上线腾讯WeTest
“刚要适配安卓派,Q就来了.” 3月14日谷歌推出了期待已久的Android Q的首个测试版本Android Q Beta 1 ,这是Android系统推出以来的第十个大版本. 安卓Q相比之前的版本, ...
- AutomaticInteger中CAS运用分析
摘要 在接触CAS的时候虽然对它流程了解了但是对其如何解决并发问题还是一直有疑问的,所以在就选择了java中典型线程安全的AtomicInteger类进行了源码的分析. CAS简介 CAS的全称为co ...
- kubenetes无法创建pod/创建RC时无法自动创建pod的问题
一.问题概述 问题1: 虽然每次通过yaml创建rc都显示成功了,但是 kubectl get pod却没显示任何的pod. 问题2: 直接通过yaml创建pod提示apixxx 问题3: 通过.js ...
- 相机标定与矫正opencv+MATLAB
博客转载自:http://blog.csdn.net/Loser__Wang/article/details/51811347 本文目的在于记录如何使用MATLAB做摄像机标定,并通过opencv进行 ...
- Python模块搜索路径
当一个名为 spam 的模块被导入的时候,解释器首先寻找具有该名称的内置模块.如果没有找到,然后解释器从 sys.path 变量给出的目录列表里寻找名为 spam.py 的文件.sys.path 初始 ...
- Web服务架构
# Web服务架构 ### Web服务模型-- 服务提供者.服务请求者.服务注册中心,服务注册中心是一个可选的角色. 现在的Web服务不仅限于WSDL,还有RESTful. - 服务提供者.即Web服 ...
- GNU Radio GRC HackRF实现FM接收
本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 淘宝店铺名称:开源SDR实验室 HackRF链接:https://item.taobao.com/item.htm?spm=a1z10.1- ...
- React Native移动开发实战-5-Android平台的调试技巧
Android平台的调试和其他平台的调试也很类似,例如:在Android Studio打开的工程中,打开源码MainActivity.java,然后,将鼠标移至代码编辑区的左侧后,单击鼠标即可添加断点 ...
- 利用Cocoapods创建基于SVN的私有库podspec
由于项目年后要进行组件化,考虑到公司内部实现的一些私有组件,不对外公开,而又想在不同项目中使用,该怎么办呢?由于cocoapods有了强大的功能,可以自己创建podspec,更可以设置私有的库.那么利 ...
- 第一章 HTML介绍
1.1 Html和CSS的关系 学习web前端开发基础技术需要掌握:HTML.CSS.JavaScript语言.下面我们就来了解下这三门技术都是用来实现什么的: 1. HTML是网页内容的载体.内容就 ...