[zoj]3573 Under Attack I

这道题是一区间统计,注意炸弹炸的是线段,最后要求的是最大的损坏值D_max,最左的具有D_max的线段的左起点,和,最右的具有D_max的线段的右起点。

因为是离线统计(废话,炸着炸药你就去修路啊~~),所以未必要用线段树

 

全长 [0, len] 在数轴上。离散也就是 0, 1, … , len-1 ( n = [n, n+1] )

 

10

1 5 2

6 9 2

 

也就是[5, 6]无损

 

[a, b] +d拆成 [a, infinity] +d, [b,infinity] -d

 

即可。

 

 

O, 上面理解错了,还是理解成点【0,len】也就是len+1个点,对【a,b】操作就是对(b-a+1)个点操作

2781797	2012-02-26 17:12:29	 Accepted	3573	C++	2140	540	wyfyw

#include <iostream>
#include <cstdio>

#include <cstdlib>
#include <cstring>

#include <string>

#include <cmath>
#include <algorithm>

using namespace std;

const int M=15005;
typedef long long LL;

LL A[M],B[M],R[M];


int main() {
    //freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
    
    int len;
    
    while(cin>>len)
    {
        memset(A,0,sizeof(A));
        memset(B,0,sizeof(B));
        int s,e,d;//start end damage
        while(scanf("%d %d %d",&s,&e,&d))
        {
            if(s==-1)break;
            if(s>e) swap(s,e);
            A[s]+=d;
            B[e+1]-=d;
        }
        int ansL=0,ansR=0;
        LL max=-1;
        LL now=0;
        
        for(int i=0; i<=len; i++)
        {
            now+=A[i]+B[i];
            R[i]=now;//restoring for the R->L traversal 
            if(max<now)
            {
                ansL=i;
                max=now;
            }            
        }
        
        for(int i=len; i>=0; i--)
        {
            if(R[i]==max) {
                ansR=i;
                break;
            }          
        }
        printf("%d %d\n",ansL,ansR);
    }
    //fclose(stdout);
    return 0;
}

  线段树写法

2781808	2012-02-26 17:19:14	 Accepted	3573	C++	3900	656	wyfyw
/*
线段树写法:
两个性质:
1、如果整段+ad,则这段的max+=ad
2、每段的max=max(lmax,rmax)+ad
//记得每次清空
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>


using namespace std;
struct node
{
    int mx,ad;
} tree[15005*4];
void build(int st,int ed,int p)
{
    tree[p].ad=0;
    tree[p].mx=0;
    if(st==ed)
    {
        return;
    }
    int m=(st+ed)/2;
    build(st,m,p*2);
    build(m+1,ed,p*2+1);
}
void insert(int st,int ed,int ll,int rr,int ad,int p)
{
    if(st==ll && ed==rr)
    {
        tree[p].ad+=ad;
        tree[p].mx+=ad;
        return;// tree[p].mx;
    }
    int m=(st+ed)/2;

    if(rr<=m)
    {
        insert(st,m,ll,rr,ad,p*2);
    }
    else if(ll>=m+1)
    {
        insert(m+1,ed,ll,rr,ad,p*2+1);
    }
    else
    {
        insert(st,m,ll,m,ad,p*2);
        insert(m+1,ed,m+1,rr,ad,p*2+1);
    }
    tree[p].mx=max(tree[p*2].mx, tree[p*2+1].mx)+tree[p].ad;
}
int findst(int st,int ed,int p)
{
    //printf("ad & mx= %d %d\n",tree[p].ad,tree[p].mx);
    if(st==ed) return st;
    int m=(st+ed)/2;
    if(tree[p*2].mx>=tree[p*2+1].mx) return findst(st,m,p*2);
    else return findst(m+1,ed,p*2+1);
}
int finded(int st,int ed,int p)
{
    if(st==ed) return st;
    int m=(st+ed)/2;
    if(tree[p*2].mx>tree[p*2+1].mx) return finded(st,m,p*2);
    else return finded(m+1,ed,p*2+1);
}
int main()
{
    int n;
    while(scanf("%d",&n) != EOF )
    {
        n++;
        build(1,n,1/*at node 1*/);//del//?[0,1]=>1...[n-1,n]=>n
        int a,b,c,i=0;
        while(scanf("%d%d%d",&a,&b,&c))
        {
            if(a>b) swap(a,b);
            if(a==-1) break;
            a++, b  ++;//del//?[st,end]=>st+1...end
            insert(1,n,a,b,c,1);
        }
        int st,ed;
        st=findst(1,n,1);
        ed=finded(1,n,1);
        printf("%d %d\n",st-1,ed  -1);//del//?
    }
    //system("pause");
}

  

posted @ 2012-02-26 17:21  ustc-acm  阅读(425)  评论(1编辑  收藏  举报