Countries

题目链接:http://hihocoder.com/problemset/problem/1391

预处理+双指针

首先将A->B,B->A的导弹全部转化为B->A的导弹(因为不需要计算B承受的伤害,所以对于A->B的导弹,只需记录被B的防护罩返回来的导弹即可).

然后对于每个导弹计算将其反弹回B,A所需要的最小的防护罩区间[l,r](这个操作在O(1)的时间完成,画张图就很好推了)

于是问题就转化为了:

数轴上有一些固定区间,每个固定区间都有一个权值,现在有一个长度为Ta的防护罩区间,问用这个防护罩区间完整包含的固定区间的权值和最大为多少?

对于这个问题,可以将固定区间的左右两端点标号,存到一个数组(struct{int position,index,value;}),然后用一个vis数组标记第index个固定区间在防护罩区间内的情况,遍历一遍防护罩区间的L即可.

代码如下:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define N 20005
#define R (L+Ta)
using namespace std;
typedef long long LL;
LL Ta,Tb,X,n,m,k,sum,pt;
bool vis[];
struct point{
LL times,index,v;
}p[];
struct node{
LL fire,fly,dam;
LL l,r;
}launch[N];
bool cmp(point a,point b){
return a.times<b.times;
}
void init(){
sum=;
memset(vis,,sizeof(vis));
memset(p,,sizeof(p));
memset(launch,,sizeof(launch));
scanf("%I64d",&X);
scanf("%I64d%I64d",&n,&m);
k=pt=;
for(LL i=;i<n;++i){
LL a,b,c;
scanf("%I64d%I64d%I64d",&a,&b,&c);
if(X<=a+b&&a+b<=X+Tb){
launch[k].fire=a+b;
launch[k].fly=b;
launch[k].dam=c;
sum+=c;
k++;
}
}
for(LL i=;i<m;++i){
scanf("%I64d%I64d%I64d",&launch[k].fire,&launch[k].fly,&launch[k].dam);
sum+=launch[k].dam;
k++;
}
for(LL i=;i<k;++i){
LL fire=launch[i].fire;
LL fly=launch[i].fly;
launch[i].l=fire+fly;
LL t=*fly;
if(fire+t<X||fire+t>X+Tb){
launch[i].r=launch[i].l;
}else{
LL len=X+Tb-fire;
LL times=len/t;
launch[i].r=launch[i].l+times*t;
}
}
for(LL i=;i<k;++i){
if(launch[i].r-launch[i].l<=Ta){
p[pt].times=launch[i].l;
p[pt].index=pt/;
p[pt++].v=launch[i].dam;
p[pt].times=launch[i].r;
p[pt].index=pt/;
p[pt++].v=launch[i].dam;
}
}
sort(p,p+pt,cmp);
}
int main(void){
while(~scanf("%I64d%I64d",&Ta,&Tb)){
init();
LL Max=;
LL temp=;
LL l=,r=,L=p[].times;
/*************防护罩L=p[0].times时的情况*************/
for(;r<pt&&p[r].times<=R;++r){
LL idx=p[r].index;
if(!vis[idx])vis[idx]=;//[L,R]内有且只有一个idx,即l在[L,R]内
else if(vis[idx]){//如果[L,R]内已经有一个idx,说明当前整个区间[l,r]都在[L,R]内
vis[idx]=;
temp+=p[r].v;
}
} /*****************将防护罩的L不断右移****************/
if(Max<temp)Max=temp;
while(r<pt){
LL idx=p[l].index;//防护罩L右移,删去l
if(!vis[idx]){//若vis[idx]为零,说明[L,R]中原来有两个idx,即现在[l,r]并不都在[L,R]内
vis[idx]=;
temp-=p[l].v;
}else if(vis[idx])vis[idx]=;//原来[l,r]就不都在[L,R]内
l++;
while(l<pt&&p[l].times==p[l-].times){//如果更改后的l与l-1相同,则需要继续处理
idx=p[l].index;
if(!vis[idx]){
vis[idx]=;
temp-=p[l].v;
}else if(vis[idx])vis[idx]=;
l++;
}
if(l==pt)break;
L=p[l].times;
for(;r<pt&&p[r].times<=R;++r){
idx=p[r].index;
if(!vis[idx])vis[idx]=;
else if(vis[idx]){
vis[idx]=;
temp+=p[r].v;
}
}
if(Max<temp)Max=temp;
}
printf("%I64d\n",sum-Max);
}
}

然而出了点问题,昨天晚上debug到三点多,一直是WA,会不会写搓了?第二天起来看了好久没看出来,会不会是算法错了?问了游少,他也表示母鸡。

回到寝室,心血来潮把I64d改成lld交了一发:PE.???.jpg

全部改成了cin,cout:AC.浪费了我一天

代码如下:

 #include<iostream>
#include<algorithm>
#include<cstring>
#define N 20005
#define R (L+Ta)
using namespace std;
typedef long long LL;
LL Ta,Tb,X,n,m,k,sum,pt;
bool vis[];
struct point{
LL times,index,v;
}p[];
struct node{
LL fire,fly,dam;
LL l,r;
}launch[N];
bool cmp(point a,point b){
return a.times<b.times;
}
void init(){
sum=;
memset(vis,,sizeof(vis));
memset(p,,sizeof(p));
memset(launch,,sizeof(launch));
cin>>X;
cin>>n>>m;
k=pt=;
for(LL i=;i<n;++i){
LL a,b,c;
cin>>a>>b>>c;
if(X<=a+b&&a+b<=X+Tb){
launch[k].fire=a+b;
launch[k].fly=b;
launch[k].dam=c;
sum+=c;
k++;
}
}
for(LL i=;i<m;++i){
cin>>launch[k].fire>>launch[k].fly>>launch[k].dam;
sum+=launch[k].dam;
k++;
}
for(LL i=;i<k;++i){
LL fire=launch[i].fire;
LL fly=launch[i].fly;
launch[i].l=fire+fly;
LL t=*fly;
if(fire+t<X||fire+t>X+Tb){
launch[i].r=launch[i].l;
}else{
LL len=X+Tb-fire;
LL times=len/t;
launch[i].r=launch[i].l+times*t;
}
}
for(LL i=;i<k;++i){
if(launch[i].r-launch[i].l<=Ta){
p[pt].times=launch[i].l;
p[pt].index=pt/;
p[pt++].v=launch[i].dam;
p[pt].times=launch[i].r;
p[pt].index=pt/;
p[pt++].v=launch[i].dam;
}
}
sort(p,p+pt,cmp);
}
int main(void){
while(cin>>Ta>>Tb){
init();
LL Max=-;
LL temp=;
LL l=,r=,L=p[].times;
for(;r<pt&&p[r].times<=R;++r){
LL idx=p[r].index;
if(!vis[idx])vis[idx]=;
else if(vis[idx]){
vis[idx]=;
temp+=p[r].v;
}
}
if(Max<temp)Max=temp;
while(r<pt){
LL idx=p[l].index;
if(!vis[idx]){
vis[idx]=;
temp-=p[l].v;
}else if(vis[idx])vis[idx]=;
l++;
while(l<pt&&p[l].times==p[l-].times){
idx=p[l].index;
if(!vis[idx]){
vis[idx]=;
temp-=p[l].v;
}else if(vis[idx])vis[idx]=;
l++;
}
if(l==pt)break;
L=p[l].times;
for(;r<pt&&p[r].times<=R;++r){
idx=p[r].index;
if(!vis[idx])vis[idx]=;
else if(vis[idx]){
vis[idx]=;
temp+=p[r].v;
}
}
if(Max<temp)Max=temp;
}
cout<<sum-Max<<endl;
}
}

Countries的更多相关文章

  1. Countries in War -POJ3114Tarjan缩点+SPFA

    Countries in War Time Limit: 1000MS Memory Limit: 65536K Description In the year 2050, after differe ...

  2. android 命名 数组 所有国家 String[] COUNTRIES

    static final String[] COUNTRIES = new String[] { "Afghanistan", "Albania", " ...

  3. 2016北京网络赛 hihocoder 1391 Countries 树状数组

    Countries   描述 There are two antagonistic countries, country A and country B. They are in a war, and ...

  4. hihocoder-1391&&北京网赛09 Countries(优先队列)

    题目链接: Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, country ...

  5. POJ 3114 Countries in War(强连通)(缩点)(最短路)

                                    Countries in War Time Limit: 1000MS   Memory Limit: 65536K Total Sub ...

  6. 离线树状数组 hihocoder 1391 Countries

    官方题解: // 离线树状数组 hihocoder 1391 Countries #include <iostream> #include <cstdio> #include ...

  7. hihoCoder 1391 Countries 【预处理+排序+堆】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)

    #1391 : Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, countr ...

  8. POJ 3114 Countries in War(强连通+最短路)

    POJ 3114 Countries in War 题目链接 题意:给定一个有向图.强连通分支内传送不须要花费,其它有一定花费.每次询问两点的最小花费 思路:强连通缩点后求最短路就可以 代码: #in ...

  9. Gephi——使用map of countries和Geo Layout实现包含地理坐标的数据可视化

    前言: Gephi(以下内容基于0.9.2)比较擅长用来处理社会网络分析,其自身以及插件对地理数据的支持非常不足.主要有以下几点: 1.map of countries这个插件可以在gephi底图上以 ...

随机推荐

  1. C语言之循环结构 for(一)

    一 for循环的介绍 语法: for(表达式1;表达式2;表达式3){ 循环体; } 循环步骤: A.执行表达式1,执行完毕跳转到B B.判断表达式2的结果是否为真,如果为真,跳转到C,否则跳转到E ...

  2. Java 编译打包命令

    背景 编译 打包 解压 运行 参考 背景 我们有的时候总是要使用将自己写的工程编译成 class 文件,同时打包成 jar,虽然有各种工具可以帮助我们,但是毕竟掌握使用 java 本来的命令去做这些更 ...

  3. javascript 数组方法解析

    测试数组:testArrayA = ['a','b','c','d','e'] , testArrayB = [2,3,6,1] 1.删除数组最后一项(pop()): 返回删除那一项的值:var po ...

  4. H3 BPM报销流程开发示例

    以报销流程为示例,介绍H3 BPM的流程开发过程. 报销流程的表单效果如下: 审核流程为填写报销申请.主管审核.总监审核(1000以上).出纳付款,显示如下: 步骤一:准备工作 使用管理员账号的登录H ...

  5. 在SQL SERVER中查找用分隔符分隔的数据

    SELECT * FROM [DB_SCJC].[dbo].[tn_Manager] 其中, CHARINDEX({1},{2})中,{1}是要查找的字符,{2}是字典库.返回值为{1}在{2}中的位 ...

  6. 数据挖掘_wget整站下载

    你应该了解的所有wget命令 翻译自All the Wget Commands You Should Know 如何下载整个网站用来离线浏览?怎样将一个网站上的所有MP3文件保存到本地的一个目录中?怎 ...

  7. 想入门webpack,这篇就够了

    申明:本文转载自简书 文/zhangwang(简书作者)原文链接:http://www.jianshu.com/p/42e11515c10f#著作权归作者所有,转载请联系作者获得授权,并标注" ...

  8. Linux下gcc,g++,gdb,scon部分用法笔记

    1 Ubuntu下编译安装GCC-4.1.2 拷贝gcc-4.1.2.tar.bz2(我下载的压缩文件)到/usr/local/src 解压 新生成的gcc-4.1.2这个目录被称为源目录,用${sr ...

  9. [ An Ac a Day ^_^ ][kuangbin带你飞]专题八 生成树 POJ 1679 The Unique MST

    求最小生成树是否唯一 求一遍最小生成树再求一遍次小生成树 看看值是否相等就可以 #include<cstdio> #include<iostream> #include< ...

  10. Cracking the Coding Interview 第二章

    2.2 链表中倒数第k个结点 输入一个链表,输出该链表中倒数第k个结点. 思路:快慢指针(error: 判断是否有可行解,否则返回null, while, if 后加空格) /* public cla ...