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 第一次AC总结(Dinic+多路增广)

这题是道神题,神就神在,它既能让你搞懂网络流及其优化,还给了你很大的优化空间。首先,说一下算法,这题就是一道最小割+简单构图的题目,增加两个节点分别表示两个CPU,第i个界点与两个CPU各连接一条,边...
  • yc5_yc
  • yc5_yc
  • 2012年04月09日 19:06
  • 1017

POJ3469 Dual Core CPU 最小割求解最小费用划分集合

题意 两个核执行n个模块,每个模块在两个核上运行花费不同 另外,m对模块如果在不同核上运行,会有额外的花费 求解最小花费的划分方式 思路 最小费用划分成两个集合,是经典的题目类型,经常会用最小割求解 ...

poj3469(最小割)

Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K Total Submissions: 23355 ...

POJ 3469 Dual Core CPU(最大流最小割定理,Dinic)

题目链接:http://poj.org/problem?id=3469 题意: 计算机中有两个CPU,SWODNIW 包含了N 个模块,每个模块必须运行在某个CPU 中。每个模块在每个CPU 中运...

Dual Core CPU POJ 3469(邻接表+GAP+CUR优化)

去网上搜了好久,终于找到了一个比较好的模板,为了长远的发展,就把它转到我的博客里来了,呵呵~~~~~ 转自:jxy859的专栏 SAP算法  最短增广路算法(Shortest Augmenting...

POJ 3469->Dual Core CPU(最大流最小割问题)

描述: Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K Total Submissions: 18147 ...

poj 3469(最大流最小割)

Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K Total Submissions: 10776 ...
  • fp_hzq
  • fp_hzq
  • 2011年08月08日 17:34
  • 627

poj 3469 Dual Core CPU 最小割+邻接表

Description As more and more computers are equipped with dual core CPU, SetagLilb, the Chief Tech...

POJ-3469- 一道标准的最小割问题

题意略 链接:http://poj.org/problem?id=3469

POJ 3469 Dual Core CPU---dinic求最大流

源点s连接 每个点,权值为Ai,此点在连接汇点t,权值为Bi;之后点 每组输入的 两点 连接无向边,即正向边和反向边都存权值。求最小割,即最大流,即为答案 自己画图感受一下吧!! #inc...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ3469
举报原因:
原因补充:

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