介绍我的三种算法

1、线段树

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

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<algorithm>
const int INF = 0x7fffffff;
using namespace std;
inline void read(long long &x) {
    long long data=0,w=1;
    char ch=0;
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
    x=data*w;
}

inline void write(long long x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

const int MAXN=1e5;
long long a[MAXN];
struct SegmentTree{
#define lson(o) (o<<1)
#define rson(o) (o<<1|1)
protected:
    long long sumv[MAXN<<2],addv[MAXN<<2];
    void pushup(int o){
        sumv[o]=sumv[lson(o)]+sumv[rson(o)];
    }
    void pushdown(int o,int l,int r){
        if(!addv[o])
            return;
        addv[lson(o)]+=addv[o];
        addv[rson(o)]+=addv[o];
        int mid=(l+r)>>1;
        sumv[lson(o)]+=addv[o]*(mid-l+1);
        sumv[rson(o)]+=addv[o]*(r-mid);
        addv[o]=0;
    }
public:
    void build(int o,int l,int r){
        addv[o]=0;
        if(l==r){//Recursive basis
            read(sumv[o]);
            return;
        }
        int mid=(l+r)>>1;
        build(lson(o),l,mid);
        build(rson(o),mid+1,r);
        pushup(o);
    }
    void optadd(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr){//Recursive basis
            addv[o]+=v;
            sumv[o]+=v*(r-l+1);
            return;
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r);
        if(ql<=mid)
            optadd(lson(o),l,mid,ql,qr,v);
        if(mid+1<=qr)
            optadd(rson(o),mid+1,r,ql,qr,v);
        pushup(o);
    }
    long long querysum(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)//Recursive basis
            return sumv[o];
        int mid=(l+r)>>1;
        long long ans=0;
        pushdown(o,l,r);
        if(ql<=mid)
            ans+=querysum(lson(o),l,mid,ql,qr);
        if(mid+1<=qr)
            ans+=querysum(rson(o),mid+1,r,ql,qr);
        return ans;
    }
}st;
int main(){
    long long n,m;
    read(n);read(m);
    //for(int i=1;i<=n;++i)
    //    read(a[i]);
    st.build(1,1,n);
    long long q,x,y,k;
    while(m--){
        read(q);
        if(q==1){
            read(x);read(y);read(k);
            st.optadd(1,1,n,x,y,k);
        }
        else if(q==2){
            read(x);read(y);
            write(st.querysum(1,1,n,x,y));
            putchar('\n');
        }
    }
    return 0;
}

2、分块

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

// luogu-judger-enable-o2
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
//#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const int INF=0x7fffffff;
template<class T> inline T read(T&x){
    T data=0;
    int w=1;
    char ch=getchar();
    while(ch!='-'&&!isdigit(ch))
        ch=getchar();
    if(ch=='-')
        w=-1,ch=getchar();
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}

const int maxn=1e5+10;
int n,m,a[maxn],belong[maxn];
int block,l[400],r[400],num,tag[400];
ll sum[400];

void build(){
    block=sqrt(n);
    num=(n-1)/block+1;
    for(int i=1;i<=num;++i)
        l[i]=(i-1)*block+1,r[i]=i*block;
    r[num]=n;
    memset(sum,0,sizeof(sum));
    memset(tag,0,sizeof(tag));
    for(int i=1;i<=n;++i){
        belong[i]=(i-1)/block+1;
        sum[belong[i]]+=a[i];
    }
}

void add(int x,int y,int k){
    if(belong[x]==belong[y]){
        sum[belong[x]]+=(y-x+1)*k;
        for(int i=x;i<=y;++i)
            a[i]+=k;
        return;
    }
    sum[belong[x]]+=(r[belong[x]]-x+1)*k;
    for(int i=x;i<=r[belong[x]];++i)
        a[i]+=k;
    for(int i=belong[x]+1;i<=belong[y]-1;++i){
        tag[i]+=k;
        sum[i]+=block*k;
    }
    sum[belong[y]]+=(y-l[belong[y]]+1)*k;
    for(int i=l[belong[y]];i<=y;++i)
        a[i]+=k;
    return;
}

ll qsum(int x,int y){
    ll ans=0;
    if(belong[x]==belong[y]){
        ans+=(y-x+1)*tag[belong[x]];
        for(int i=x;i<=y;++i)
            ans+=a[i];
        return ans;
    }
    ans+=(r[belong[x]]-x+1)*tag[belong[x]];
    for(int i=x;i<=r[belong[x]];++i)
        ans+=a[i];
    for(int i=belong[x]+1;i<=belong[y]-1;++i)
        ans+=sum[i];
    ans+=(y-l[belong[y]]+1)*tag[belong[y]];
    for(int i=l[belong[y]];i<=y;++i)
        ans+=a[i];
    return ans;
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n);read(m);
    for(int i=1;i<=n;++i)
        read(a[i]);
    build();
    int op,x,y,k;
    for(int i=1;i<=m;++i){
        read(op);
        switch(op){
            case 1:{
                read(x);read(y);read(k);
                add(x,y,k);
                break;
            }
            case 2:{
                read(x);read(y);
                printf("%lld\n",qsum(x,y));
                break;
            }
        }
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

3、树状数组

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e5+7;
int n;
ll sum1[MAXN],sum2[MAXN];

int lowbit(int x)
{
    return x&-x;
}

void add(int p,ll v)
{
    for(int i=p;i<=n;i+=lowbit(i))
    {
        sum1[i]+=v,sum2[i]+=p*v;
    }
}

void range_add(int l,int r,ll v)
{
    add(l,v);
    add(r+1,-v);
}

ll ask(int p)
{
    ll res=0;
    for(int i=p;i;i-=lowbit(i))
    {
        res+=(p+1)*sum1[i]-sum2[i];
    }
    return res;
}

ll range_ask(int l,int r)
{
    return ask(r)-ask(l-1);
}

/*void add(ll p, ll x){
    for(int i = p; i <= n; i += i & -i)
        sum1[i] += x, sum2[i] += x * p;
}
void range_add(ll l, ll r, ll x){
    add(l, x), add(r + 1, -x);
}
ll ask(ll p){
    ll res = 0;
    for(int i = p; i; i -= i & -i)
        res += (p + 1) * sum1[i] - sum2[i];
    return res;
}
ll range_ask(ll l, ll r){
    return ask(r) - ask(l - 1);
}*/
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int m;
    read(n);read(m);
    for(int i=1;i<=n;++i)
    {
        int a;
        read(a);
        range_add(i,i,a);
    }
    while(m--)
    {
        int opt;
        read(opt);
        if(opt==1)
        {
            int l,r;
            ll v;
            read(l);read(r);read(v);
            range_add(l,r,v);
        }
        else
        {
            int l,r;
            read(l);read(r);
            printf("%lld\n",range_ask(l,r));
        }
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

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. LeetCode--104--二叉树的最大深度

    问题描述: 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例: 给定二叉树 [3,9,20,null,null, ...

  2. codeforces 700a//As Fast As Possible// Codeforces Round #364(Div. 1)

    题意:n个人要运动ll长,有个bus带其中几个人,问最短时间 最后所有人在同一时间到终点是用时最少的.由于搭bus相当于加速,每个人的加速时间应该一样.先计算bus走过的路程route.看第一个人被搭 ...

  3. 『cs231n』作业1选讲_通过代码理解KNN&交叉验证&SVM

    通过K近邻算法探究numpy向量运算提速 茴香豆的“茴”字有... ... 使用三种计算图片距离的方式实现K近邻算法: 1.最为基础的双循环 2.利用numpy的broadca机制实现单循环 3.利用 ...

  4. Educational Codeforces Round 47 (Rated for Div. 2)F. Dominant Indices 线段树合并

    题意:有一棵树,对于每个点求子树中离他深度最多的深度是多少, 题解:线段树合并快如闪电,每个节点开一个权值线段树,递归时合并即可,然后维护区间最多的是哪个权值,到x的深度就是到根的深度减去x到根的深度 ...

  5. Android将view保存为图片并放在相册中

    在Android中,可以将view保存为图片并放在相册中,步骤为 view->bitmap->file,即先将view转化为bitmap,再将bitmap保存到相册中. 需要将红框标注的v ...

  6. bind出现Address already in use解决方法

    在socket函数和bind函数之间加入一段代码: // 建立服务器端socket if((server_sockfd = socket(AF_INET, SOCK_STREAM, 0))<0) ...

  7. 【转】在SQL Server中创建用户角色及授权(使用SQL语句)

    1. 首先在 SQL Server 服务器级别,创建登陆帐户(create login) --创建登陆帐户(create login) create login dba with password=' ...

  8. POJ 1860 Bellman-Ford算法

    转载链接:http://blog.csdn.net/lyy289065406/article/details/6645778 提示:关键在于反向利用Bellman-Ford算法 题目大意 有多种汇币, ...

  9. SQL Server 调优系列基础篇 - 性能调优介绍

    前言 关于SQL Server调优系列是一个庞大的内容体系,非一言两语能够分析清楚,本篇先就在SQL 调优中所最常用的查询计划进行解析,力图做好基础的掌握,夯实基本功!而后再谈谈整体的语句调优. 通过 ...

  10. HDU 4091 Zombie’s Treasure Chest 分析 难度:1

    Zombie’s Treasure Chest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...