先貼一下自己的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;
}