zoj 3573 Under Attack(线段树 标记法 最大覆盖数)

原创 2015年07月08日 12:30:04
Under Attack




Time Limit:  10 Seconds      Memory Limit:  65536 KB 




Doctor serves at a military air force base. One day, the enemy launch a sudden attack and the base is under heavy fire. The fighters in the airport must take off to intercept enemy bombers. However, the enemies know this clearly and they now focus on destroying the runway. The situation is becoming worse rapidly! 


Every part of the runway has a damage level. On each bombing run, the damage level is increased by the bomb's damage . Fortunately, the enemy bombers has to stop bombing the runway when they run out of ammo. Then the ground crew have time to evaluate the situation of runway so that they can come to repair the runway ASAP after enemy attacks. The most heavily-damaged part on fighters' taking off and landing path should first be repaired. Assume that runway start from north and head to south , and fighters will take off or land only from north to south or vice versa. 


Now that the task is clear, the ground crew need the cooridinates of two points: first that is the most damaged point from north to south, second is the most damaged point from south to north.The base's central mainframe is down under hacker attack. So Doctor could only use his poor little and shabby notebook to fulfill this task. Can you help him? 


Input


The input consists of multiple cases. 
The first line is the runway length L. L can be up to 15000.
 Next lines will describe enemy bombing runs ,each line describes effect range start end of each bombing run and enemy bomb damage d.if start is -1, this case ends..
There can be up to 3000 bombing run, each time the damage is up to 100. 
 Notice that the bombing range is from north to south, and runway range is [0,len].




Output


Output the cooridinates of two points: first that is the most damaged point from north to south, second is the most damaged point from south to north. 


Sample Input
10
1 5 2
6 9 2
-1 -1 -1




Sample Output
1 9




从早上起 这都一上午了,这个大水题终于a了!在不知道 最大覆盖次数求法之前,我先求出全长线段中最大值,也就是普通的区间更新加延迟标记,然后利用calculate函数从两边分别开始遍历找到左右最大值的位置,从多组测试数据上来看 ,并没有什么差错,但就是wrong,后学会最大覆盖次数,1a。
见到的请帮我看看到底是哪些 数据错了!!!!!!


第二段代码是正确地;


wrong code:
#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cctype>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int INF=15003;
struct Tree
{
    int left;
    int right;
    int mark;
    int Max;
} tree[INF<<2];

int create(int root,int left,int right)
{
    tree[root].left=left;
    tree[root].right=right;
    if(left==right)
    {
        return tree[root].Max=0;
    }
    int a,b,middle=(left+right)>>1;
    a=create(root<<1,left,middle);
    b=create(root<<1|1,middle+1,right);
    return tree[root].Max=max(a,b);
}

void update_mark(int root)
{
    if(tree[root].mark)
    {
        tree[root].Max+=tree[root].mark;
        if(tree[root].left!=tree[root].right)
        {
            tree[root<<1].mark+=tree[root].mark;
            tree[root<<1|1].mark+=tree[root].mark;
        }
        tree[root].mark=0;
    }
}

int calculate(int root,int left ,int right)
{
    update_mark(root);
    if(tree[root].left>right||tree[root].right<left)
        return 0;
    if(tree[root].left>=left&&tree[root].right<=right)
    {
        return tree[root].Max;
    }
    int a,b;
    a=calculate(root<<1,left,right);
    b=calculate(root<<1|1,left,right);
    return max(a,b);
}

int   update(int root,int left,int right,int val)
{
    update_mark(root);
    if(tree[root].left>right||tree[root].right<left)
        return tree[root].Max;
    if(tree[root].left>=left&&tree[root].right<=right)
    {
        tree[root].mark+=val;
        update_mark(root);
        return tree[root].Max;
    }
    int a=update(root<<1,left,right,val);
    int b=update(root<<1|1,left,right,val);
    return tree[root].Max=max(a,b);

}

int main()
{
    int L;
    while(scanf("%d",&L)!=EOF)
    {
        create(1,0,L);
        int x,y,z;
        while(scanf("%d%d%d",&x,&y,&z)!=EOF)
        {
            if(x>y)
                swap(x,y);
            if(x!=-1)
            {
                update(1,x,y,z);
            }
            else break;
        }
        int k=calculate(1,0,L);
        int locl,locr;
        for(int i=0; i<=L;i++)
        {
            if(calculate(1,i,i)==k)
            {

                locl=i;
                break;
            }
        }
        for(int i=L;i>=0;i--)
        {
            if(calculate(1,i,i)==k)
            {
                locr=i;
                break;
            }
        }
        printf("%d,%d\n",locl,locr);
    }
    return 0;
}
/*
10
1 2  3
0 0 3
5 8 4
0 0 3
2 2 2
-1 1 3
*/
</pre><pre name="code" class="cpp">正确 代码:
<pre name="code" class="cpp">#include<stdio.h>
struct Tree
{
    int left,right,cover;
} tree[15000<<2];
int covered=0;
void create(int root,int left,int right)
{
    tree[root].left=left;
    tree[root].right=right;
    tree[root].cover=0;
    if(right==left)
        return ;
    int mid=(left+right)>>1;
    create(root<<1,left,mid);
    create(root<<1|1,mid+1,right);
}

void update(int root,int left,int right,int val)
{
    if(left<=tree[root].left&&tree[root].right<=right)
    {
        tree[root].cover+=val;
        return ;
    }
    int m=(tree[root].left+tree[root].right)>>1;
    if(m>=left)update(root<<1,left,right,val);
    if(m<right)update(root<<1|1,left,right,val);
}

void  calculate(int root,int x)
{
    covered+=tree[root].cover;
    if(tree[root].left==tree[root].right)
        return ;
    int m=(tree[root].left+tree[root].right)>>1;
    if(m>=x)
        calculate(root<<1,x);
    else
        calculate(root<<1|1,x);

}

int main()
{
    int L;
    while(scanf("%d",&L)!=EOF)
    {
        create(1,0,L);
        int x,y,z;
        while(scanf("%d%d%d",&x,&y,&z))
        {
            if(x==-1)
                break;
            update(1,x,y,z);
        }
        int loc1, loc2,Max=0;
        for(int i=0; i<=L; i++)
        {
            covered=0;
            calculate(1,i);
            if(covered>Max)
            {
                Max=covered;
                loc1=i;
            }
        }
        for(int i=L,Max=0; i>=0; i--)
        {
            covered=0;
            calculate(1,i);
            if(covered>Max)
            {
                Max=covered;
                loc2=i;
            }
        }
        printf("%d %d\n",loc1,loc2);
    }
    return 0;
}




版权声明:强烈建议大家加入(Java)全国各校IT精英! 群号 467123855 里面都是大神各种分享 内推渠道 (我的老豆比IT站被阿里销毁了。。。)

相关文章推荐

zoj3573 Under Attack (线段树)

这是ZOJ Monthly, February 2012的C题,比赛时我提交了好几次结果都是Segmentation Fault。我也不知道这是什么错误,检查了好几遍代码也没发现有什么问题。今天又重敲...
  • ahfywff
  • ahfywff
  • 2012年02月26日 13:12
  • 537

ZOJ3574 Under Attack II【线段树】

题意:在x=a,x=b之间的区域,有n条直线,问区域被划分成几块。 思路:把左边排序,每次插入一条线,看有几个交点,每有一个比它大的数就有一个交点,ans += 交点数 + 1(ans初始化...
  • wjw1340
  • wjw1340
  • 2017年08月06日 19:00
  • 48

ZOJ--3574--Under Attack II【线段树+欧拉公式】

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3574 题意:一个坐标系,给出x1、x2限定左右边界,有n条直线,告诉...
  • zzzz40
  • zzzz40
  • 2014年11月20日 23:50
  • 764

zoj 3573 Under Attack

更新的时候一定要确保更新到最后一排子节点,一开始忽略这个了,交了很多遍都是WA,所有的更新后在加一次更新,确保所有节点的add值为0.就可以了。 #include #includ...

zoj 3573 Under Attack

类型:线段树 题目:给定一个区间,依次对某些区间添加权值,求从右端开始权值最大的点和从左端开始权值最大的点 来源:113 - ZOJ Monthly, February 2012 !!!对于长度...

zoj 3573 Under Attack

题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4595 大概题意:对区间进行一些小区间的增量操作,求最大值的最左端点...
  • lwbaptx
  • lwbaptx
  • 2012年03月27日 17:17
  • 807

线段树模板 zoj1128

  • 2010年08月31日 11:50
  • 5KB
  • 下载

线段树模板(lazy标记)ZOJ 3686

题解:先搜索用将树上的点给定时间戳,以此当做该节点的区间。 #include #include #include using namespace std; #define N 150005 bo...
  • Tsaid
  • Tsaid
  • 2013年04月03日 23:25
  • 1255

zoj 2706 Thermal Death of the Universe(线段树区间更新+懒惰标记)

Thermal Death of the Universe Time Limit: 10 Seconds      Memory Limit: 32768 KB Johnie has recen...

线段树区间修改 lazy标记 大法

#include #include #define maxn 100000 + 10 #define Lson L, mid, rt
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:zoj 3573 Under Attack(线段树 标记法 最大覆盖数)
举报原因:
原因补充:

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