[CF936D]World of Tank
作者:互联网
World of Tank
题解
相当有趣的
d
p
dp
dp题。
显然,如果我们要开炮击毁一个建筑,我们是可以提前在许多个位置开炮的,只要 CD 好了就可以开炮。
如果我们要将 CD 放到状态中的话,是相当麻烦的,毕竟 CD 是
1
0
9
10^9
109级别的。
事实上这里有一种更好地方法,我们可以不这样记录,我们记录我们可以存储多少的 CD 不用,等着撞到了障碍物,再将这些存着的 CD 消耗掉,表示在这些 CD 满时就打炮,再继续存储剩余的 CD。
这样就可以将我们的 CD 放到
d
p
dp
dp之里面,显然 CD 值是屯的越多越好的,所以我们取得肯定是
d
p
dp
dp值的最大值。
在换道的时候,由于你没法提前开炮了,只能冷却你的炮,所以这时候需要将
d
p
dp
dp值与
t
t
t去
m
i
n
min
min。
最后我们可以通过
d
p
dp
dp值还原出我们的操作路径。
但这样
d
p
dp
dp状态还是太多了,
n
n
n是
1
0
9
10^9
109级别的。
我们发现我们转道肯定只会在障碍物之后转,而开炮有与状态无关。
所以我们只需要将所有的障碍物和其后一个位置加入
d
p
dp
dp状态,离散化一下就只有
m
1
+
m
2
m1+m2
m1+m2级别的状态了。
时间复杂度 O ( ( m 1 + m 2 ) log ( m 1 + m 2 ) ) O\left((m1+m2)\log\,(m1+m2)\right) O((m1+m2)log(m1+m2))。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 2000005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
typedef long double ld;
typedef pair<int,int> pii;
const LL INF=0x7f7f7f7f7f7f7f7f;
const int mo=1e9+7;
const int inv2=5e8+4;
const int jzm=23333;
const int zero=20000;
const int lim=1000000;
const int orG=3,ivG=334845270;
const double Pi=acos(-1.0);
const double eps=1e-12;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;}return t;}
int n,m1,m2,b[MAXN],tot,cnt,pre[MAXN][2],dp[MAXN][2],t;
bool maze[MAXN][2];
vector<int>ans1;
vector<pii>ans2;
struct ming{int x,y;}s[MAXN];
signed main(){
read(n);read(m1);read(m2);read(t);b[++tot]=1;
for(int i=1,x;i<=m1;i++)read(x),s[++cnt]=(ming){x,0},b[++tot]=x,b[++tot]=x+1;
for(int i=1,x;i<=m2;i++)read(x),s[++cnt]=(ming){x,1},b[++tot]=x,b[++tot]=x+1;
sort(b+1,b+tot+1);tot=unique(b+1,b+tot+1)-b-1;
for(int i=1;i<=cnt;i++)s[i].x=lower_bound(b+1,b+tot+1,s[i].x)-b,maze[s[i].x][s[i].y]=1;
memset(dp,-0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=tot;i++){
int dif=b[i]-b[i-1];
for(int j=0;j<2;j++){
if(!maze[i][j]&&dp[i-1][j]>=0){
dp[i][j]=max(dp[i][j],dp[i-1][j]+dif);
if(dp[i-1][j]+dif==dp[i][j])pre[i][j]=0;
}
if(maze[i][j]&&dp[i-1][j]+dif>t){
dp[i][j]=max(dp[i][j],dp[i-1][j]-t+dif);
if(dp[i-1][j]-t+dif==dp[i][j])pre[i][j]=0;
}
if(!maze[i][j]&&!maze[i-1][j]&&dp[i-1][j^1]>=0){
dp[i][j]=max(dp[i][j],min(dp[i-1][j^1],t)+dif);
if(min(dp[i-1][j^1],t)+dif==dp[i][j])pre[i][j]=1;
}
if(maze[i][j]&&!maze[i-1][j]&&dp[i-1][j^1]+dif>t){
dp[i][j]=max(dp[i][j],min(dp[i-1][j^1],t)+dif-t);
if(min(dp[i-1][j^1],t)+dif-t==dp[i][j])pre[i][j]=1;
}
}
}
if(dp[tot][0]<0&&dp[tot][1]<0){puts("No");return 0;}
int now=dp[tot][0]>=0?0:1,pos=tot,siz;
while(pos){
int nxt=now^pre[pos][now];if(nxt^now)ans1.pb(b[pos-1]);
if(maze[pos][now])ans2.pb(mkpr(b[pos]-dp[pos][now],2-(now^1)));
now=nxt;pos--;
}
puts("Yes");
printf("%d\n",siz=ans1.size());reverse(ans1.begin(),ans1.end());
for(int i=0;i<siz;i++)printf("%d ",ans1[i]);puts("");
printf("%d\n",siz=ans2.size());reverse(ans2.begin(),ans2.end());
for(int i=0;i<siz;i++)printf("%d %d\n",ans2[i].fir,ans2[i].sec);
return 0;
}
谢谢!!!
标签:Tank,int,dif,tot,CD,CF936D,World,dp,const 来源: https://blog.csdn.net/Tan_tan_tann/article/details/122395500