介绍我的三种算法

1、线段树

既然这题是线段树板子,我还是尊重一下先发这个。跑的时间376ms不是很快,但也还是不错。O(nlogn)。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<string>
  7. #include<vector>
  8. #include<stack>
  9. #include<queue>
  10. #include<set>
  11. #include<map>
  12. #include<algorithm>
  13. const int INF = 0x7fffffff;
  14. using namespace std;
  15. inline void read(long long &x) {
  16. long long data=0,w=1;
  17. char ch=0;
  18. while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
  19. if(ch=='-') w=-1,ch=getchar();
  20. while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
  21. x=data*w;
  22. }
  23. inline void write(long long x) {
  24. if(x<0) putchar('-'),x=-x;
  25. if(x>9) write(x/10);
  26. putchar(x%10+'0');
  27. }
  28. const int MAXN=1e5;
  29. long long a[MAXN];
  30. struct SegmentTree{
  31. #define lson(o) (o<<1)
  32. #define rson(o) (o<<1|1)
  33. protected:
  34. long long sumv[MAXN<<2],addv[MAXN<<2];
  35. void pushup(int o){
  36. sumv[o]=sumv[lson(o)]+sumv[rson(o)];
  37. }
  38. void pushdown(int o,int l,int r){
  39. if(!addv[o])
  40. return;
  41. addv[lson(o)]+=addv[o];
  42. addv[rson(o)]+=addv[o];
  43. int mid=(l+r)>>1;
  44. sumv[lson(o)]+=addv[o]*(mid-l+1);
  45. sumv[rson(o)]+=addv[o]*(r-mid);
  46. addv[o]=0;
  47. }
  48. public:
  49. void build(int o,int l,int r){
  50. addv[o]=0;
  51. if(l==r){//Recursive basis
  52. read(sumv[o]);
  53. return;
  54. }
  55. int mid=(l+r)>>1;
  56. build(lson(o),l,mid);
  57. build(rson(o),mid+1,r);
  58. pushup(o);
  59. }
  60. void optadd(int o,int l,int r,int ql,int qr,int v){
  61. if(ql<=l&&r<=qr){//Recursive basis
  62. addv[o]+=v;
  63. sumv[o]+=v*(r-l+1);
  64. return;
  65. }
  66. int mid=(l+r)>>1;
  67. pushdown(o,l,r);
  68. if(ql<=mid)
  69. optadd(lson(o),l,mid,ql,qr,v);
  70. if(mid+1<=qr)
  71. optadd(rson(o),mid+1,r,ql,qr,v);
  72. pushup(o);
  73. }
  74. long long querysum(int o,int l,int r,int ql,int qr){
  75. if(ql<=l&&r<=qr)//Recursive basis
  76. return sumv[o];
  77. int mid=(l+r)>>1;
  78. long long ans=0;
  79. pushdown(o,l,r);
  80. if(ql<=mid)
  81. ans+=querysum(lson(o),l,mid,ql,qr);
  82. if(mid+1<=qr)
  83. ans+=querysum(rson(o),mid+1,r,ql,qr);
  84. return ans;
  85. }
  86. }st;
  87. int main(){
  88. long long n,m;
  89. read(n);read(m);
  90. //for(int i=1;i<=n;++i)
  91. // read(a[i]);
  92. st.build(1,1,n);
  93. long long q,x,y,k;
  94. while(m--){
  95. read(q);
  96. if(q==1){
  97. read(x);read(y);read(k);
  98. st.optadd(1,1,n,x,y,k);
  99. }
  100. else if(q==2){
  101. read(x);read(y);
  102. write(st.querysum(1,1,n,x,y));
  103. putchar('\n');
  104. }
  105. }
  106. return 0;
  107. }

2、分块

对此题这种O(nsqrt(n))的算法竟然更快...可能是因为常数很小+o2。192ms。

  1. // luogu-judger-enable-o2
  2. #include<cstdlib>
  3. #include<cstdio>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<ctime>
  7. #include<iostream>
  8. #include<string>
  9. #include<vector>
  10. #include<list>
  11. #include<deque>
  12. #include<stack>
  13. #include<queue>
  14. #include<map>
  15. #include<set>
  16. #include<algorithm>
  17. //#pragma GCC optimize(2)
  18. using namespace std;
  19. typedef long long ll;
  20. const int INF=0x7fffffff;
  21. template<class T> inline T read(T&x){
  22. T data=0;
  23. int w=1;
  24. char ch=getchar();
  25. while(ch!='-'&&!isdigit(ch))
  26. ch=getchar();
  27. if(ch=='-')
  28. w=-1,ch=getchar();
  29. while(isdigit(ch))
  30. data=10*data+ch-'0',ch=getchar();
  31. return x=data*w;
  32. }
  33. const int maxn=1e5+10;
  34. int n,m,a[maxn],belong[maxn];
  35. int block,l[400],r[400],num,tag[400];
  36. ll sum[400];
  37. void build(){
  38. block=sqrt(n);
  39. num=(n-1)/block+1;
  40. for(int i=1;i<=num;++i)
  41. l[i]=(i-1)*block+1,r[i]=i*block;
  42. r[num]=n;
  43. memset(sum,0,sizeof(sum));
  44. memset(tag,0,sizeof(tag));
  45. for(int i=1;i<=n;++i){
  46. belong[i]=(i-1)/block+1;
  47. sum[belong[i]]+=a[i];
  48. }
  49. }
  50. void add(int x,int y,int k){
  51. if(belong[x]==belong[y]){
  52. sum[belong[x]]+=(y-x+1)*k;
  53. for(int i=x;i<=y;++i)
  54. a[i]+=k;
  55. return;
  56. }
  57. sum[belong[x]]+=(r[belong[x]]-x+1)*k;
  58. for(int i=x;i<=r[belong[x]];++i)
  59. a[i]+=k;
  60. for(int i=belong[x]+1;i<=belong[y]-1;++i){
  61. tag[i]+=k;
  62. sum[i]+=block*k;
  63. }
  64. sum[belong[y]]+=(y-l[belong[y]]+1)*k;
  65. for(int i=l[belong[y]];i<=y;++i)
  66. a[i]+=k;
  67. return;
  68. }
  69. ll qsum(int x,int y){
  70. ll ans=0;
  71. if(belong[x]==belong[y]){
  72. ans+=(y-x+1)*tag[belong[x]];
  73. for(int i=x;i<=y;++i)
  74. ans+=a[i];
  75. return ans;
  76. }
  77. ans+=(r[belong[x]]-x+1)*tag[belong[x]];
  78. for(int i=x;i<=r[belong[x]];++i)
  79. ans+=a[i];
  80. for(int i=belong[x]+1;i<=belong[y]-1;++i)
  81. ans+=sum[i];
  82. ans+=(y-l[belong[y]]+1)*tag[belong[y]];
  83. for(int i=l[belong[y]];i<=y;++i)
  84. ans+=a[i];
  85. return ans;
  86. }
  87. int main()
  88. {
  89. // freopen(".in","r",stdin);
  90. // freopen(".out","w",stdout);
  91. read(n);read(m);
  92. for(int i=1;i<=n;++i)
  93. read(a[i]);
  94. build();
  95. int op,x,y,k;
  96. for(int i=1;i<=m;++i){
  97. read(op);
  98. switch(op){
  99. case 1:{
  100. read(x);read(y);read(k);
  101. add(x,y,k);
  102. break;
  103. }
  104. case 2:{
  105. read(x);read(y);
  106. printf("%lld\n",qsum(x,y));
  107. break;
  108. }
  109. }
  110. }
  111. // fclose(stdin);
  112. // fclose(stdout);
  113. return 0;
  114. }

3、树状数组

  1. #include<cstdlib>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<ctime>
  6. #include<iostream>
  7. #include<string>
  8. #include<vector>
  9. #include<list>
  10. #include<deque>
  11. #include<stack>
  12. #include<queue>
  13. #include<map>
  14. #include<set>
  15. #include<bitset>
  16. #include<algorithm>
  17. #include<complex>
  18. #pragma GCC optimize ("O0")
  19. using namespace std;
  20. template<class T> inline T read(T&x)
  21. {
  22. T data=0;
  23. int w=1;
  24. char ch=getchar();
  25. while(!isdigit(ch))
  26. {
  27. if(ch=='-')
  28. w=-1;
  29. ch=getchar();
  30. }
  31. while(isdigit(ch))
  32. data=10*data+ch-'0',ch=getchar();
  33. return x=data*w;
  34. }
  35. typedef long long ll;
  36. const int INF=0x7fffffff;
  37. const int MAXN=1e5+7;
  38. int n;
  39. ll sum1[MAXN],sum2[MAXN];
  40. int lowbit(int x)
  41. {
  42. return x&-x;
  43. }
  44. void add(int p,ll v)
  45. {
  46. for(int i=p;i<=n;i+=lowbit(i))
  47. {
  48. sum1[i]+=v,sum2[i]+=p*v;
  49. }
  50. }
  51. void range_add(int l,int r,ll v)
  52. {
  53. add(l,v);
  54. add(r+1,-v);
  55. }
  56. ll ask(int p)
  57. {
  58. ll res=0;
  59. for(int i=p;i;i-=lowbit(i))
  60. {
  61. res+=(p+1)*sum1[i]-sum2[i];
  62. }
  63. return res;
  64. }
  65. ll range_ask(int l,int r)
  66. {
  67. return ask(r)-ask(l-1);
  68. }
  69. /*void add(ll p, ll x){
  70. for(int i = p; i <= n; i += i & -i)
  71. sum1[i] += x, sum2[i] += x * p;
  72. }
  73. void range_add(ll l, ll r, ll x){
  74. add(l, x), add(r + 1, -x);
  75. }
  76. ll ask(ll p){
  77. ll res = 0;
  78. for(int i = p; i; i -= i & -i)
  79. res += (p + 1) * sum1[i] - sum2[i];
  80. return res;
  81. }
  82. ll range_ask(ll l, ll r){
  83. return ask(r) - ask(l - 1);
  84. }*/
  85. int main()
  86. {
  87. // freopen(".in","r",stdin);
  88. // freopen(".out","w",stdout);
  89. int m;
  90. read(n);read(m);
  91. for(int i=1;i<=n;++i)
  92. {
  93. int a;
  94. read(a);
  95. range_add(i,i,a);
  96. }
  97. while(m--)
  98. {
  99. int opt;
  100. read(opt);
  101. if(opt==1)
  102. {
  103. int l,r;
  104. ll v;
  105. read(l);read(r);read(v);
  106. range_add(l,r,v);
  107. }
  108. else
  109. {
  110. int l,r;
  111. read(l);read(r);
  112. printf("%lld\n",range_ask(l,r));
  113. }
  114. }
  115. // fclose(stdin);
  116. // fclose(stdout);
  117. return 0;
  118. }

LG3372 【【模板】线段树 1】的更多相关文章

  1. hdu 1754 I Hate It (模板线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=1754 I Hate It Time Limit: 9000/3000 MS (Java/Others)    M ...

  2. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  3. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  4. 【线段树】【P3372】模板-线段树

    百度百科 Definition&Solution 线段树是一种log级别的树形结构,可以处理区间修改以及区间查询问题.期望情况下,复杂度为O(nlogn). 核心思想见百度百科,线段树即将每个 ...

  5. 算法模板——线段树6(二维线段树:区域加法+区域求和)(求助phile)

    实现功能——对于一个N×M的方格,1:输入一个区域,将此区域全部值作加法:2:输入一个区域,求此区域全部值的和 其实和一维线段树同理,只是不知道为什么速度比想象的慢那么多,求解释...@acphile ...

  6. 【洛谷 p3373】模板-线段树 2(数据结构--线段树)

    题意:已知一个数列,你需要进行下面三种操作:1.将某区间每一个数加上x:2.将某区间每一个数乘上x:3.求出某区间每一个数的和. 解法:(唉 :-(,这题卡住我了......)对于加法和乘法的混合操作 ...

  7. 【洛谷 p3372】模板-线段树 1(数据结构--线段树)

    题目:已知一个数列,你需要进行下面两种操作:1.将某区间每一个数加上x:2.求出某区间每一个数的和. 解法:如题,模版题.需要加上 lazy 标记,也就是我的 upd.lazy 标记的思路就是对一个结 ...

  8. hdu 1754 I Hate It (线段树、单点更新)(PS:ios::sync_with_stdio(false)可以加快cin、cout的读取写出速度)

    I Hate ItTime Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  9. poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...

  10. 线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543

    学习博客推荐——线段树+扫描线(有关扫描线的理解) 我觉得要注意的几点 1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1] 2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个pu ...

随机推荐

  1. [.NET源码] EF的增删改查

    EF的增删改查 创建上下文对象:WordBoradEntities db = new WordBoradEntities(); 一.添加: //1.1创建实体对象 User uObj = new Us ...

  2. English trip V1 - 3.What Would you Like? Teacher:Lamb Key: would like to

    In this lesson you will learn to talk about fast food and health. would = will 的过去式 STARTER 1.Tell y ...

  3. layui的富文本编辑器怎么赋值

    除了上面讲的方法外,还可以使用layedit自带的方法赋值/*** 设置编辑器内容* @param {[type]} index 编辑器索引* @param {[type]} content 要设置的 ...

  4. gradle 编译 No such property: sonatypeUsername错误解决

    No such property: sonatypeUsername for class: org.gradle.api.publication.maven.internal.ant.DefaultG ...

  5. 连接ACCESS

    access2000-2003数据库连接字符串: ConStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=数据库名.mdb"; ...

  6. JavaScript 对象的使用

    JavaScript支持面向对象的编程方法. 2.9.1 window对象(窗口对象)的常用方法 内部函数 alert ( ) ,实际上是 window 对象的方法,写成全称为 window . al ...

  7. redhat linux 6.2 安装配置GUI

    redhat6.2默认不安装GUI,启动时默认进入text模式,下面介绍下安装.配置GUI的步骤: 1.登录root 2.配置及测试yum   vi /etc/yum.repos.d/rhel-sou ...

  8. hadoop hbase install (2)

    reference: http://dblab.xmu.edu.cn/blog/install-hbase/ reference: http://dblab.xmu.edu.cn/blog/2139- ...

  9. 跟我一起学习ASP.NET 4.5 MVC4.0(一)

    跟我一起学习ASP.NET 4.5 MVC4.0(一)   由于上面一个项目使用的是ASP.NET4.0 MVC3.0,在招人的时候发现很多人有听说过MVC,但是却是没用过,对MVC也只是一知半解,最 ...

  10. 【转载】oracle索引详解

    原文URL;http://www.oschina.net/question/30362_4057?fromerr=FiY27yLL 作者:crazyinsomnia 一. ROWID的概念 存储了ro ...