zoukankan      html  css  js  c++  java
  • 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即可.

    代码如下:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #define N 20005
      5 #define R (L+Ta)
      6 using namespace std;
      7 typedef long long LL;
      8 LL Ta,Tb,X,n,m,k,sum,pt;
      9 bool vis[50005];
     10 struct point{
     11     LL times,index,v;
     12 }p[50005];
     13 struct node{
     14     LL fire,fly,dam;
     15     LL l,r;
     16 }launch[N];
     17 bool cmp(point a,point b){
     18     return a.times<b.times;
     19 }
     20 void init(){
     21     sum=0;
     22     memset(vis,0,sizeof(vis));
     23     memset(p,0,sizeof(p));
     24     memset(launch,0,sizeof(launch));
     25     scanf("%I64d",&X);
     26     scanf("%I64d%I64d",&n,&m);
     27     k=pt=0;
     28     for(LL i=0;i<n;++i){
     29         LL a,b,c;
     30         scanf("%I64d%I64d%I64d",&a,&b,&c);
     31         if(X<=a+b&&a+b<=X+Tb){
     32             launch[k].fire=a+b;
     33             launch[k].fly=b;
     34             launch[k].dam=c;
     35             sum+=c;
     36             k++;
     37         }
     38     }
     39     for(LL i=0;i<m;++i){
     40         scanf("%I64d%I64d%I64d",&launch[k].fire,&launch[k].fly,&launch[k].dam);
     41         sum+=launch[k].dam;
     42         k++;
     43     }
     44     for(LL i=0;i<k;++i){
     45         LL fire=launch[i].fire;
     46         LL fly=launch[i].fly;
     47         launch[i].l=fire+fly;
     48         LL t=2*fly;
     49         if(fire+t<X||fire+t>X+Tb){
     50             launch[i].r=launch[i].l;
     51         }else{
     52             LL len=X+Tb-fire;
     53             LL times=len/t;
     54             launch[i].r=launch[i].l+times*t;
     55         }
     56     }
     57     for(LL i=0;i<k;++i){
     58         if(launch[i].r-launch[i].l<=Ta){
     59             p[pt].times=launch[i].l;
     60             p[pt].index=pt/2;
     61             p[pt++].v=launch[i].dam;
     62             p[pt].times=launch[i].r;
     63             p[pt].index=pt/2;
     64             p[pt++].v=launch[i].dam;
     65         }
     66     }
     67     sort(p,p+pt,cmp);
     68 }
     69 int main(void){
     70     while(~scanf("%I64d%I64d",&Ta,&Tb)){
     71         init();
     72         LL Max=0;
     73         LL temp=0;
     74         LL l=0,r=0,L=p[0].times;
     75         /*************防护罩L=p[0].times时的情况*************/
     76         for(;r<pt&&p[r].times<=R;++r){
     77             LL idx=p[r].index;
     78             if(!vis[idx])vis[idx]=1;//[L,R]内有且只有一个idx,即l在[L,R]内
     79             else if(vis[idx]){//如果[L,R]内已经有一个idx,说明当前整个区间[l,r]都在[L,R]内
     80                 vis[idx]=0;
     81                 temp+=p[r].v;
     82             }
     83         }
     84 
     85         /*****************将防护罩的L不断右移****************/
     86         if(Max<temp)Max=temp;
     87         while(r<pt){
     88             LL idx=p[l].index;//防护罩L右移,删去l
     89             if(!vis[idx]){//若vis[idx]为零,说明[L,R]中原来有两个idx,即现在[l,r]并不都在[L,R]内
     90                 vis[idx]=1;
     91                 temp-=p[l].v;
     92             }else if(vis[idx])vis[idx]=0;//原来[l,r]就不都在[L,R]内
     93             l++;
     94             while(l<pt&&p[l].times==p[l-1].times){//如果更改后的l与l-1相同,则需要继续处理
     95                 idx=p[l].index;
     96                 if(!vis[idx]){
     97                     vis[idx]=1;
     98                     temp-=p[l].v;
     99                 }else if(vis[idx])vis[idx]=0;
    100                 l++;
    101             }
    102             if(l==pt)break;
    103             L=p[l].times;
    104             for(;r<pt&&p[r].times<=R;++r){
    105                 idx=p[r].index;
    106                 if(!vis[idx])vis[idx]=1;
    107                 else if(vis[idx]){
    108                     vis[idx]=0;
    109                     temp+=p[r].v;
    110                 }
    111             }
    112             if(Max<temp)Max=temp;
    113         }
    114         printf("%I64d
    ",sum-Max);
    115     }
    116 }
    View Code

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

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

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

    代码如下:

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #define N 20005
      5 #define R (L+Ta)
      6 using namespace std;
      7 typedef long long LL;
      8 LL Ta,Tb,X,n,m,k,sum,pt;
      9 bool vis[50005];
     10 struct point{
     11     LL times,index,v;
     12 }p[50005];
     13 struct node{
     14     LL fire,fly,dam;
     15     LL l,r;
     16 }launch[N];
     17 bool cmp(point a,point b){
     18     return a.times<b.times;
     19 }
     20 void init(){
     21     sum=0;
     22     memset(vis,0,sizeof(vis));
     23     memset(p,0,sizeof(p));
     24     memset(launch,0,sizeof(launch));
     25     cin>>X;
     26     cin>>n>>m;
     27     k=pt=0;
     28     for(LL i=0;i<n;++i){
     29         LL a,b,c;
     30         cin>>a>>b>>c;
     31         if(X<=a+b&&a+b<=X+Tb){
     32             launch[k].fire=a+b;
     33             launch[k].fly=b;
     34             launch[k].dam=c;
     35             sum+=c;
     36             k++;
     37         }
     38     }
     39     for(LL i=0;i<m;++i){
     40         cin>>launch[k].fire>>launch[k].fly>>launch[k].dam;
     41         sum+=launch[k].dam;
     42         k++;
     43     }
     44     for(LL i=0;i<k;++i){
     45         LL fire=launch[i].fire;
     46         LL fly=launch[i].fly;
     47         launch[i].l=fire+fly;
     48         LL t=2*fly;
     49         if(fire+t<X||fire+t>X+Tb){
     50             launch[i].r=launch[i].l;
     51         }else{
     52             LL len=X+Tb-fire;
     53             LL times=len/t;
     54             launch[i].r=launch[i].l+times*t;
     55         }
     56     }
     57     for(LL i=0;i<k;++i){
     58         if(launch[i].r-launch[i].l<=Ta){
     59             p[pt].times=launch[i].l;
     60             p[pt].index=pt/2;
     61             p[pt++].v=launch[i].dam;
     62             p[pt].times=launch[i].r;
     63             p[pt].index=pt/2;
     64             p[pt++].v=launch[i].dam;
     65         }
     66     }
     67     sort(p,p+pt,cmp);
     68 }
     69 int main(void){
     70     while(cin>>Ta>>Tb){
     71         init();
     72         LL Max=-1;
     73         LL temp=0;
     74         LL l=0,r=0,L=p[0].times;
     75         for(;r<pt&&p[r].times<=R;++r){
     76             LL idx=p[r].index;
     77             if(!vis[idx])vis[idx]=1;
     78             else if(vis[idx]){
     79                 vis[idx]=0;
     80                 temp+=p[r].v;
     81             }
     82         }
     83         if(Max<temp)Max=temp;
     84         while(r<pt){
     85             LL idx=p[l].index;
     86             if(!vis[idx]){
     87                 vis[idx]=1;
     88                 temp-=p[l].v;
     89             }else if(vis[idx])vis[idx]=0;
     90             l++;
     91             while(l<pt&&p[l].times==p[l-1].times){
     92                 idx=p[l].index;
     93                 if(!vis[idx]){
     94                     vis[idx]=1;
     95                     temp-=p[l].v;
     96                 }else if(vis[idx])vis[idx]=0;
     97                 l++;
     98             }
     99             if(l==pt)break;
    100             L=p[l].times;
    101             for(;r<pt&&p[r].times<=R;++r){
    102                 idx=p[r].index;
    103                 if(!vis[idx])vis[idx]=1;
    104                 else if(vis[idx]){
    105                     vis[idx]=0;
    106                     temp+=p[r].v;
    107                 }
    108             }
    109             if(Max<temp)Max=temp;
    110         }
    111         cout<<sum-Max<<endl;
    112     }
    113 }
  • 相关阅读:
    bzoj2124 等差子序列(树状数组+hash)
    CF817F MEX Queries(线段树上二分)
    [USACO12MAR]摩天大楼里的奶牛(状态压缩DP)
    CF786B Legacy(线段树优化建图)
    绿豆蛙的归宿
    单选错位
    聪聪和可可
    Tyvj1952 Easy
    OSU!
    弱题
  • 原文地址:https://www.cnblogs.com/barrier/p/5906980.html
Copyright © 2011-2022 走看看