[codevs3235] 战争 - 矩形切割


题目描述

2050年,人类与外星人之间的战争已趋于白热化。就在这时,人类发明出一种超级武器,这种武器能够同时对相邻的多个目标进行攻击。凡是防御力小于或等于这种武器攻击力的外星人遭到它的攻击,就会被消灭。然而,拥有超级武器是远远不够的,人们还需要一个战地统计系统时刻反馈外星人部队的信息。这个艰巨的任务落在你的身上。请你尽快设计出这样一套系统。
这套系统需要具备能够处理如下2类信息的能力:
  1.外星人向[x1,x2]内的每个位置增援一支防御力为v的部队。
  2.人类使用超级武器对[x1,x2]内的所有位置进行一次攻击力为v的打击。系统需要返回在这次攻击中被消灭的外星人个数。
注:防御力为i的外星人部队由i个外星人组成,其中第j个外星人的防御力为j。


输入格式

从文件War.in第一行读入n,m。其中n表示有n个位置,m表示有m条信息。
以下有m行,每行有4个整数k,x1,x2,v用来描述一条信息 。k表示这条信息属于第k类。x1,x2,v为相应信息的参数。k=1 or 2。
注:你可以认为最初的所有位置都没有外星人存在。
规模:0< n <= 1000; 0 < x1 <= x2 <= n; 0 < v <= 1000; 0 < m <= 2000


输出格式

结果输出到文件War.out。按顺序输出需要返回的信息。


样例数据

样例输入

3 5
1 1 3 4
2 1 2 3
1 1 2 2
1 2 3 1
2 2 3 5

样例输出

6
9


题目分析

题目描述有点不清楚,其实是防御力取最大的那个,因此可以转为矩形切割做
将每一个命令看做带权线段,那么就可以把带权线段展开成二维
(l,r,v)->(l-1,0,r,v)
因此就可以矩形切割了
至于能不能线段树,应该可以吧?懒得写了


源代码

#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
    int num=0,bj=1;
    char x=getchar();
    while(x<'0'||x>'9') {
        if(x=='-')bj=-1;
        x=getchar();
    }
    while(x>='0'&&x<='9') {
        num=num*10+x-'0';
        x=getchar();
    }
    return num*bj;
}
struct Square {
    double x1,x2,y1,y2;
    Square() {}
    Square(double lx,double ly,double rx,double ry):x1(lx),y1(ly),x2(rx),y2(ry) {}
} ;
struct Cut_Square {
    Square a[100005];
    int sum;
    int init() {
        sum=0;
    }
    bool if_intersect(Square a,Square b) {
        if(a.x1>=b.x2||a.y1>=b.y2||a.x2<=b.x1||a.y2<=b.y1)return false;
        else return true;
    }
    void add(double x1,double y1,double x2,double y2) {
        a[++sum]=Square(x1,y1,x2,y2);
    }
    void del(int index) {
        a[index]=a[sum];
        sum--;
    }
    double Xway_cut(int index,double x1,double y1,double x2,double y2) { //返回交集 
        double k1=max(x1,a[index].x1);
        double k2=min(x2,a[index].x2);
        if(a[index].x1<k1)add(a[index].x1,a[index].y1,k1,a[index].y2);
        if(k2<a[index].x2)add(k2,a[index].y1,a[index].x2,a[index].y2);
        return Yway_cut(index,k1,y1,k2,y2);
    }
    double Yway_cut(int index,double x1,double y1,double x2,double y2) {
        double k1=max(y1,a[index].y1);
        double k2=min(y2,a[index].y2);
        if(a[index].y1<k1)add(x1,a[index].y1,x2,k1);
        if(k2<a[index].y2)add(x1,k2,x2,a[index].y2);
        return (x2-x1)*(k2-k1);
    }
};
Cut_Square s;
int n,m;
int main() {
    n=Get_Int();
    m=Get_Int();
    for(int i=1; i<=m; i++) {
        int order=Get_Int(),x1=Get_Int(),x2=Get_Int(),v=Get_Int();
        if(order==1)s.add(x1-1,0,x2,v);
        else {
            x1=x1-1;
            int y1=0,y2=v;
            int sum=0;
            Square b(x1,y1,x2,y2);
            for(int j=1; j<=s.sum; j++) {
                if(!s.if_intersect(s.a[j],b))continue;
                sum+=s.Xway_cut(j,x1,y1,x2,y2);
                s.del(j);
                j--;
            }
            printf("%d\n",sum);
        }
    }
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值