其他分享
首页 > 其他分享> > [CF936D]World of Tank

[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