Countries
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的更多相关文章
- Countries in War -POJ3114Tarjan缩点+SPFA
Countries in War Time Limit: 1000MS Memory Limit: 65536K Description In the year 2050, after differe ...
- android 命名 数组 所有国家 String[] COUNTRIES
static final String[] COUNTRIES = new String[] { "Afghanistan", "Albania", " ...
- 2016北京网络赛 hihocoder 1391 Countries 树状数组
Countries 描述 There are two antagonistic countries, country A and country B. They are in a war, and ...
- hihocoder-1391&&北京网赛09 Countries(优先队列)
题目链接: Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, country ...
- POJ 3114 Countries in War(强连通)(缩点)(最短路)
Countries in War Time Limit: 1000MS Memory Limit: 65536K Total Sub ...
- 离线树状数组 hihocoder 1391 Countries
官方题解: // 离线树状数组 hihocoder 1391 Countries #include <iostream> #include <cstdio> #include ...
- hihoCoder 1391 Countries 【预处理+排序+堆】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2016)网络赛)
#1391 : Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, countr ...
- POJ 3114 Countries in War(强连通+最短路)
POJ 3114 Countries in War 题目链接 题意:给定一个有向图.强连通分支内传送不须要花费,其它有一定花费.每次询问两点的最小花费 思路:强连通缩点后求最短路就可以 代码: #in ...
- Gephi——使用map of countries和Geo Layout实现包含地理坐标的数据可视化
前言: Gephi(以下内容基于0.9.2)比较擅长用来处理社会网络分析,其自身以及插件对地理数据的支持非常不足.主要有以下几点: 1.map of countries这个插件可以在gephi底图上以 ...
随机推荐
- JqGrid在行中自定义自己的东西
$.fn.fmatter.actions = function(cellval, opts) { function baseOption(obj) { return { url: obj.url || ...
- junit 注意事项,切记
Junit 依赖于 hamcrest jar包,所以在用@Test注解的时候 junit-xxx.jar hamcrest-core-xx.jar hamcrest-library-xx.jar ...
- Selenium也是一个用于Web应用程序测试的工具
Selenium也是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE.Mozilla Firefox.Mozilla Suite ...
- console.dir()和console.log()的区别
console.log()可以取代alert()或document.write(),在网页脚本中使用console.log(data)时,会在控制台打印出数据. console.dir()可以显示一个 ...
- MATLAB中的多项式运算
作者:长沙理工大学 交通运输工程学院 王航臣 1.多项式求根 在MATLAB中求取多项式的根用roots函数. 函数:roots 功能:一元高次方程求解. 语法:roots(c) 说明:返回一个列向量 ...
- 复习java7 集合的底层实现理解
1.ArrayList 特点:查询快,增删慢,可以重复,无序 实现:底层是用数组实现的,在添加数据的时候,当数组已经满了,会扩容,默认增加1.5倍的原数组长度,并将旧的数组数据拷贝到新的数组上. 2. ...
- Tarjan算法详解
Tarjan算法详解 今天偶然发现了这个算法,看了好久,终于明白了一些表层的知识....在这里和大家分享一下... Tarjan算法是一个求解极大强联通子图的算法,相信这些东西大家都在网络上百度过了, ...
- 通过linux的iso镜像安装(RPM)扩展工具包
通过linux的iso镜像安装(RPM)扩展工具包 在linux安装软件时,现在越来越流行通过rpm指令安装完成,原因是:采用RPM安装简单方便:越来越多的软件提供RPM安装包:linux的IOS镜像 ...
- linux 安装php的redis拓展
安装步骤: #wget https://github.com/nicolasff/phpredis/archive/2.2.4.tar.gz #tar -zxvf 2.2.4 #cd phpredi ...
- 3-Dom
HTML DOM 对象DOM DocumentDOM ElementDOM AttributeDOM Event Document对象 每个载入浏览器的 HTML 文档都会成为 Document 对象 ...