[CF936D]World of Tank
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 mingint 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;
谢谢!!!
以上是关于[CF936D]World of Tank的主要内容,如果未能解决你的问题,请参考以下文章
CF1321-World of Darkraft: Battle for Azathoth (线段树+二维偏序)