妙啊



先貼一下自己的10分鐘30分暴力。。。

#include <ctime>  
#include <string>  
#include <cstring>  
#include<cstdio>
#include <cstdlib>  
#include <iostream>  
#include <algorithm>  
  #include<set> 
#include <vector>  
#include<queue>
#include<map>
#define pb push_back 

#define forup(i,a,b) for(int i=(a);i<=(b);i++)  
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)  
  
#define maxn 100005 
#define maxm 100005 
#define INF 1070000000  
using namespace std;  
typedef long long ll;  
typedef unsigned long long ull;  
  map<int,int>  p[maxn];
template<class T> inline  
void read(T& num){   num = 0; bool f = true;char ch = getchar();   while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();}  while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();}   num = f ? num: -num; } 
int out[100]; 
template<class T> inline 
void write(T x,char ch){  if (x==0) {putchar('0'); putchar(ch); return;} if (x<0) {putchar('-'); x=-x;}int num=0; while (x){ out[num++]=(x%10); x=x/10;} fordown(i,num-1,0) putchar(out[i]+'0'); putchar(ch); } 
/*==================split line==================*/
int Ta,Tb;
int stB;
struct Node
{int st,len,d;}; Node nodeA[maxn],nodeB[maxn];
int n,m;
int main()
{  while(cin>>Ta>>Tb)
  { 
   { read(stB);
     read(n);read(m);
      forup(i,1,n)   { read(nodeA[i].st);read(nodeA[i].len);read(nodeA[i].d);}
    forup(i,1,m) { read(nodeB[i].st); read(nodeB[i].len); read(nodeB[i].d);} 
   }
   int cmin=INF; 
	forup(i,0,200)
	  { int ans=0;
	    forup(j,1,n)
	      {int f=0,st=nodeA[j].st; 
		   while(1)
	          { f=1-f;
			     st=st+nodeA[j].len;
			     if(f==1)
				 {if(st>Tb+stB||st<stB)  {break;}
			     }
			     if(f==0)
			      {if(st>Ta+i||st<i) {ans=ans+nodeA[j].d;break;}
				  }
			  }
		  }
	     forup(j,1,m)
	     {int f=1,st=nodeB[j].st; 
		   while(1)
	          { f=1-f;
			     st=st+nodeB[j].len;
			     if(f==1)
				 {if(st>Tb+stB||st<stB)  {break;}
			     }
			     if(f==0)
			      {if(st>Ta+i||st<i) {ans=ans+nodeB[j].d;break;}
				  }
			  }
		  }
	   cmin=min(ans,cmin);
	  }
     write(cmin,'\n'); 
	 } 
	return 0;
 } 

然後說一下標算。顯然我們可以看出要能擋住某一個導彈需要一段連續的區間,而每一個導彈的開始結束時間是可以O(1)算出來的,可以先假設A國護盾一直開着,然後所有的導彈就相當於一個有開始和結束時間的事件,那麼我們線性掃描一遍就好了。。。

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#define LL long long
using namespace std;
 
template<class T> inline
void read(T& x) {
    x=0; char c=getchar(); while(!isdigit(c)) c=getchar();
    while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
}
 
int n,m,ta,tb,t,x[160005][3],lll,li,i,j,a,b,c,d,e,z[160005],zh[160005][3],ls[320005];
LL ans,all,num[320005];
 
inline bool cmp1(int a,int b) {return zh[a][0]<zh[b][0];}
 
inline bool cmp2(int a,int b) {return zh[a][1]<zh[b][1];}
 
inline void ddoo(int a,int b,int c,int d) {
    if(a<b-c) return; zh[++lll][0]=b-c;
    if(zh[lll][0]<0) zh[lll][0]=0; zh[lll][1]=a; zh[lll][2]=d;
}
 
int main() {
    while(scanf("%d%d",&ta,&tb)!=EOF) {
        read(t); read(n); read(m); lll=li=ans=all=0; memset(num,0,sizeof num);
        while(n--) {
            read(a); read(b); read(c); if(a+b<t||a+b>t+tb) continue;
            x[++li][2]=c; c=t+tb-a-b; x[li][0]=a+2*b; c=c/2/b+1; x[li][1]=a+c*2*b;
        }
        while(m--) {
            read(a); read(b); read(c); x[++li][2]=c; x[li][0]=a+b;
            if(a+b+b<t||a+b+b>t+tb) x[li][1]=a+b;
            else {
                c=t+tb-a; c=c/2/b+1; x[li][1]=a+b*(2*c-1);
            }
        }
        for(i=1;i<=li;++i) all=all+x[i][2],ddoo(x[i][0],x[i][1],ta,x[i][2]);
        for(i=1;i<=lll;++i) z[i]=i,ls[i*2-1]=zh[i][0],ls[i*2]=zh[i][1];
        sort(ls+1,ls+lll*2+1);
        for(j=1,i=2;i<=lll*2;++i) {
            if(ls[i]==ls[j]) continue; ls[++j]=ls[i];
        } d=j;
        sort(z+1,z+lll+1,cmp1);
        for(i=1,j=1;i<=lll;++i) {while(zh[z[i]][0]>ls[j]) ++j; zh[z[i]][0]=j;}
        sort(z+1,z+lll+1,cmp2);
        for(i=1,j=1;i<=lll;++i) {while(zh[z[i]][1]>ls[j]) ++j; zh[z[i]][1]=j;}
        for(i=1;i<=lll;++i) num[zh[i][0]]=num[zh[i][0]]+zh[i][2],num[zh[i][1]+1]=num[zh[i][1]+1]-zh[i][2];
        ans=num[1];
        for(i=2;i<=d;++i) {num[i]=num[i-1]+num[i]; if(num[i]>ans) ans=num[i];}
        printf("%lld\n",all-ans);
    }
    return 0;
}      


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章