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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

poj3469 - Dual Core CPU

想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410                                ...
  • wangjian8006
  • wangjian8006
  • 2012年08月31日 23:23
  • 1409

POJ3469 Dual Core CPU

邻接表求最小割。
  • H992109898
  • H992109898
  • 2016年04月21日 16:41
  • 520

poj3469(*最小割模型)

/* translation: 要在核A与核B组成的双核cpu上面运行n个模块,给出每个模块在核A、核B上运行的时间。除此之外,接下来还有m组需要交换数据的 模块。每当两组模块在一个核...
  • qq_29169749
  • qq_29169749
  • 2017年02月09日 22:17
  • 60

poj3469

#include #include #include #include #include #define MAX 20010 using namespace std; struct node { i...
  • killua7080
  • killua7080
  • 2012年10月25日 16:57
  • 329

poj3469(最大流最小割问题)

题目链接:http://poj.org/problem?id=3469 Dual Core CPU Time Limit: 15000MS   Memo...
  • asdfghjkl1993
  • asdfghjkl1993
  • 2014年05月13日 13:54
  • 891

poj3469 Dinic

Dinic 模板 以后做题就用这个模板了。 题意:一台双核电脑,给你多个任务,分别给出每个任务在第一个核和第二个核上运行的消耗。后面的m行输入是给出两个任务在两个不同核上运行需要付出的额外消耗。 ...
  • Non_Cease
  • Non_Cease
  • 2011年08月31日 10:51
  • 1408

poj3469(最小割)

Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K Total Submissions: 23355 ...
  • martinue
  • martinue
  • 2016年10月11日 15:09
  • 177

网络流-poj3469

Language: Default Dual Core CPU Time Limit: 15000MS   Memory Limit: 131072K Total Submissions...
  • u010660276
  • u010660276
  • 2013年10月05日 21:26
  • 534

poj3469最小割

14496k 10297MS C++ 数据量有点吓人,这题15s,真尼马神题 构图方法:将两个处理器分别作为源点和汇点。然后将任务作为中间节点。从源点向所有的节点都连一条边,以Ai为...
  • Kevin_Samuel
  • Kevin_Samuel
  • 2013年08月21日 19:03
  • 740

POJ3469 代码

Source CodeProblem: 3469 User: forsonaMemory: 14596K Time: 3329MSLanguage: C++ Result: AcceptedSourc...
  • fOrmkNight
  • fOrmkNight
  • 2009年04月21日 20:44
  • 7440
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ3469
举报原因:
原因补充:

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