bzoj1558: [JSOI2009]等差数列
来源:互联网 发布:des密码算法 编辑:程序博客网 时间:2024/05/24 04:51
传送门
显然直接维护比较萎。
考虑差分。
然后一次操作就变成了一次区间加,两次单点加。
直接用线段树维护以下就可以了。
注意标记合并时不要手残。
#include<cstdio>#include<cstdlib>#include<iostream>#include<cmath>#include<cstring>#include<algorithm>using namespace std;int n,q,l,r,a,b,s[100005];char fl[5];inline void re(int &x,int y){ if (y<x) x=y;}struct data{ int s[4],l,r; data operator +(data y){ data c; c.l=l,c.r=y.r; c.s[0]=s[2]+y.s[1]-(r==y.l); re(c.s[0],s[0]+y.s[1]),re(c.s[0],s[2]+y.s[0]); c.s[1]=s[3]+y.s[1]-(r==y.l); re(c.s[1],s[1]+y.s[1]),re(c.s[1],s[3]+y.s[0]); c.s[2]=s[2]+y.s[3]-(r==y.l); re(c.s[2],s[2]+y.s[2]),re(c.s[2],s[0]+y.s[3]); c.s[3]=s[3]+y.s[3]-(r==y.l); re(c.s[3],s[3]+y.s[2]),re(c.s[3],s[1]+y.s[3]); return c; }};struct node{ int l,r,val; data x;}t[400005];void pushdown(int x){ int l=x*2,r=x*2+1; t[l].val+=t[x].val; t[r].val+=t[x].val; t[l].x.l+=t[x].val; t[r].x.l+=t[x].val; t[l].x.r+=t[x].val; t[r].x.r+=t[x].val; t[x].val=0;}void build(int x,int l,int r){ t[x].l=l; t[x].r=r; if (l==r){ t[x].x.s[0]=0; t[x].x.l=t[x].x.r=s[l]; t[x].x.s[1]=t[x].x.s[2]=t[x].x.s[3]=1; return; } int mid=(l+r)/2; build(x*2,l,mid); build(x*2+1,mid+1,r); t[x].x=t[x*2].x+t[x*2+1].x;}data ask(int k,int x,int y){ int l=t[k].l,r=t[k].r,mid=(l+r)/2; if (l==x&&r==y) return t[k].x; if (t[k].val) pushdown(k); if (y<=mid) return ask(k*2,x,y); if (x>mid) return ask(k*2+1,x,y); return ask(k*2,x,mid)+ask(k*2+1,mid+1,y);}void change(int k,int x,int y,int v){ int l=t[k].l,r=t[k].r,mid=(l+r)/2; if (l==x&&r==y){ t[k].val+=v; t[k].x.l+=v; t[k].x.r+=v; return; } if (t[k].val) pushdown(k); if (y<=mid) change(k*2,x,y,v); else if (x>mid) change(k*2+1,x,y,v); else change(k*2,x,mid,v),change(k*2+1,mid+1,y,v); t[k].x=t[k*2].x+t[k*2+1].x;}int main(){ scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&s[i]); for (int i=1;i<n;i++) s[i]=s[i+1]-s[i]; build(1,1,n-1); scanf("%d",&q); while (q--){ scanf("%s%d%d",fl,&l,&r); if (fl[0]=='B'){ if (l==r) printf("1\n"); else printf("%d\n",ask(1,l,r-1).s[3]); } else{ scanf("%d%d",&a,&b); if (l!=1) change(1,l-1,l-1,a); if (l!=r) change(1,l,r-1,b); if (r!=n) change(1,r,r,-(a+(r-l)*b)); } } return 0;}
0 0
- bzoj1558: [JSOI2009]等差数列
- [省选] [线段树] [差分数组] [BZOJ1558] [JSOI2009] 等差数列
- bzoj 1558: [JSOI2009]等差数列 (线段树)
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- 等差数列
- C语言之数据结构
- 树的创建,与基本操作
- Linear Regression
- 用HTML5做2048游戏(一)
- RecyclerView的万能适配器
- bzoj1558: [JSOI2009]等差数列
- 复习笔记-局部与成员变量
- unity使用Zxing的.net库搞二维码与条形码的事
- Django使用Mysql数据库已经存在的数据表
- 第一天的改变
- 网络编程细节总结
- iOS 开发一些常用插件和第三方库的整理
- 函数的递归调用实例
- unit2.7访问网络文件共享服务