【第22期】观点:IT 行业加班,到底有没有价值?

POJ3469

原创 2016年05月30日 11:52:48

线段树解法:
本题需要成段更新区间,所以 为了保护线段树的高效,对每个节点,我们维护一下两个数据。

a.给这个节点对应的区间内的所有原始共同加上的值。
b.在这个节点对应的区间中除去a之外其他的值的和。

通过单独维护共同加上的值,给区间同时加上一个值的操作就可以高效的进行了。如果对于父亲节点同时加上一个值,那么这个值就不会在儿子节点被重复考虑。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>


using namespace std;


typedef long long LL;
typedef pair<int,int> pii;
const int MAXN = 1E5 + 10;
const int INF = 1E9;
const int dat_size = 4*MAXN;

//输入
int n,q;
int A[MAXN];
char t[MAXN];
int L[MAXN],R[MAXN];
int X[MAXN];

//线段树

LL s1[4*MAXN],s2[4*MAXN];

//对区间[a,b)同时加x
void add(int a, int b,int x,int k,int l,int r)
{
    if(a<=l&&r<=b)
    {
        s1[k] += x;

    }else if(l<b&&r>a)
    {
        s2[k] += (min(b,r)-max(a,l))*x;
        add(a,b,x,k*2+1,l,(l+r)/2);
        add(a,b,x,k*2+2,(l+r)/2,r);
    }
}

LL sum(int a,int b,int k,int l,int r)
{
    if(b<=l||a>=r)
    {
        return 0;
    }
    else if(a <= l && r <=b)
    {
        return s1[k]*(r-l) +s2[k];
    }
    else {
        LL res = (min(b,r)-max(a,l))*s1[k];
        res += sum(a,b,k*2+1,l,(l+r)/2);
        res += sum(a,b,k*2+2,(l+r)/2,r);
        return res;
    }
}

void solve()
{
    for(int i=0 ;i<n; i++)
    {
        add(i,i+1,A[i],0,0,n);
    }
    for(int i = 0 ;i < q ; i++)
    {
        if(t[i] == 'C')
        {
            add(L[i]-1,R[i],X[i],0,0,n);
        }
        else {
                printf("%lld\n",sum(L[i]-1,R[i],0,0,n));


        }
    }
}

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&A[i]);
    }
    for(int i=0;i<q;i++)
    {
        scanf(" %c ",&t[i]);
        if(t[i]=='C')
        {
            scanf("%d%d%d",&L[i],&R[i],&X[i]);
        }
        else {
            scanf("%d%d",&L[i],&R[i]);
        }
    }
    solve();
    return 0;
}

树状数组解法:

如果给区间[l,r)同时加上x每个节点的值将会

令 s(i) = 加上x之前的sigma(a[j])
s’[i] = 加上x之后的sigma(a[j])

那么就有 i < l 时s’[i] = s[i]
l<= i <=r 时 s’[i] = s[i] +x*(i-l+1)
= s[i] +x*l -x*(l-1)

r < i 时 s’[i] = s[i] +x(r-l +1)

下面记 sum(bit,i)为树状数组的前i项和。我们可以构建两个B树状数组bit0,bit1。
并且设
sigma(a[j]) = sum(bit1,i) *i + sum(bit0,i)
那么在[l,r) 区间上同时加上x就可以看成是
1.在bit0的L位置上加上-x(l-1)
2.在bit1的L位置上加上x
3.在bit0的R+1位置上加上XR
4.在bit1的R+1位置上加上-x

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<set>
#include<cmath>


using namespace std;


const int maxn = 1e5 + 10;
typedef long long LL;

//输入

int n,q;
int A[maxn];
char T[maxn];
int L[maxn],R[maxn],X[maxn];


//BIT;

LL bit0[maxn],bit1[maxn];


LL sum(LL *b,int i)
{
    LL s = 0;
    while(i > 0)
    {
        s += b[i];
        i -= i&-i;
    }
    return s;
}

void add(LL *b,int i,int v)
{
    while(i <= n)
    {
       // cout<<-1<<endl;
        b[i] += v;
        i += i&-i;
    }
}


void solve()
{

    for(int i=1;i<=n;i++)
    {
        add(bit0,i,A[i]);
    }
    for(int i=1;i<=q;i++)
    {
        if(T[i]=='C')
        {
            add(bit0,L[i],-X[i]*(L[i]-1));
            add(bit1,L[i],X[i]);
            add(bit0,R[i]+1,X[i]*R[i]);
            add(bit1,R[i]+1,-X[i]);
        }
        else {
            LL res = 0;
            res += sum(bit0,R[i]) + sum(bit1,R[i])*R[i];
            res -= sum(bit0,L[i]-1) + sum(bit1,L[i]-1)*(L[i]-1);
            printf("%lld\n",res);
        }
    }
}

int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&A[i]);
    }
    for(int i=1;i<=q;i++)
    {
        scanf(" %c ",&T[i]);
        if(T[i]=='C')
        {
            scanf("%d%d%d",&L[i],&R[i],&X[i]);
        }else{
            scanf("%d%d",&L[i],&R[i]);
        }
    }
    solve();
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

poj 3469 网络流最小割

http://poj.org/problem?id=3469 Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K...

POJ3469 - 构造图..做最大流..

这道题初看和网络流完全没关系.....以前做的一些网络流都是些模板题....这道题就要自己来构图了... 首先假设没有后面的两两不共存需要代价的条件....也就是只要一个程序去A处理器要多少代价...去B处理器要多少代价...问总共的最小代价.. 构造图...源点为A处理器...中间一列需要执行的程序...汇点为B处理器..源点向所有的中间点做边...容量为每个程序放在A处理器执行的代价...所有中间点向汇点做边..容量为每个程序放在B处理器执行的代价....做一次最大流...可以发现得到的最大流即为所需的最小代价.... 现在加入

POJ-3469 Dual Core CPU 网络流

题意:一台双核电脑,给你多个任务,分别给出每个任务在第一个核和第二个核上运行的消耗。后面的m行输入是给出两个任务在两个不同核上运行需要付出的额外消耗。 建图:把每个任务作为节点,在超级源点与任务间的...

poj 3469 Dual Core CPU (最小割模型)

ACM确实是需要毅力的东西,最近刷网络流,竭尽全力的一个ac。。。 把题目中的模型转换成最小割模型,然后就是模版了 为什么是最小割?因为显然任意一个割中模块只能多放不能少,而满足条件的一定是一个割,所以满足条件的就是极小割,所有极小割也满足条件,最小割是极小割,所以花费最小的就是最小割 <span style="fo

POJ 3469 Dual Core CPU

一堆任务分配到2个不同的芯片上运行,一个任务在不同芯片上运行的时间不一样,有一些任务组如果分配到不同的芯片上运行会产生额外的时间.... 用最小的费用将不同对象划分到两个集合 , 最小割问题 .   ...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)