https://www.luogu.com.cn/discuss/new?forum=CF1866E
这个题是我在一个小赛上遇到的(唯一改变的条件就是N,最大为300),赛后调题始终调不出来(结果在底部),请各位大佬帮忙
目前感觉是DP转移可能有问题,尤其可能是ST表访问代入值有问题,但是没检查出来
#include<bits/stdc++.h>
using namespace std;
long long read()
{
long long x=0;
short f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')
{
f*=(-1);
}
c=getchar();
}
while(c>='0'&&c<='9')
{
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
void wit(long long x)
{
if(x==0)
{
return ;
}
wit(x/10);
putchar(x%10+'0');
return ;
}
void write(long long x,bool edl)
{
if(x<=0)
{
if(x==0)
{
putchar('0');
}else{
putchar('-');
wit(x*(-1));
}
}else{
wit(x);
}
if(edl)
{
putchar('\n');
}else{
putchar(' ');
}
}
void test(bool end)
{
puts("TEST");
if(end)
{
exit(0);
}
return ;
}
const long long LLM=1e16;
long long upd[2][305][305][6],dp[2][305][305][6],st[3][200005][20][2],a[3][305],ans=LLM+1;
//关于upd,这是个标记更新时间的函数,防止滚动数组访问之前的数据
//dp[滚动数组的一位][一个电梯上次执行任务的时间][另一个电梯上次执行任务的时间][剩下那个去执行上次的任务的电梯编号]
//st[电梯编号(0~2)][启示位置][长度是2的多少幂次][方向]
//a[电梯编号][天数]
int n,q;
vector<pair<long long,long long> >li;
//li表示任务列表,没有任务的一天会用<LLM,LLM>代替
vector<int>lg2;
long long mi(int l,int r,int i)
{
if(r<l)
{
swap(r,l);
}
return min(st[i][l][lg2[r-l+1]][0],st[i][r][lg2[r-l+1]][1]);
}//st表查询函数
void up(int i,int x,int y,int e,long long a)
{
if(upd[i%2][x][y][e]<i)
{
dp[i%2][x][y][e]=a;
upd[i%2][x][y][e]=i;
}else{
dp[i%2][x][y][e]=min(dp[i%2][x][y][e],a);
}
return ;
}//dp更新函数,可以检查dp值是否过期
int main()
{
//freopen("elevator.in","r",stdin);
//freopen("elevator.out","w",stdout);
long long ai,opt,l,r,las,lasi,laslasi;
bool stp[3]={false};
n=read();
q=read();
for(int i=1;i<=q;i++)
{
ai=read();
a[0][i]=ai;
a[1][i]=ai;
a[2][i]=ai;
}
lg2.push_back(0);
lg2.push_back(0);
for(int i=2;i<=q+1;i++)
{
lg2.push_back(lg2[i >> 1]+1);
}
li.push_back(make_pair(0,1));
for(int i=1;i<=q;i++)
{
opt=read();
if(opt==1)
{
l=read();
r=read();
}else{
l=read();
stp[l-1]=!stp[l-1];
l=LLM;
r=LLM;
}
li.push_back(make_pair(l,r));
if(stp[0])
{
a[0][i]=INT_MAX;
}
if(stp[1])
{
a[1][i]=INT_MAX;
}
if(stp[2])
{
a[2][i]=INT_MAX;
}//对于关闭的电梯,将该电梯在改天的费用改为INT_MAX
}
for(int i=0;i<=2;i++)
{
st[i][0][0][0]=INT_MAX;
st[i][0][0][1]=INT_MAX;
//第0天是不能调控电梯的,所以费用为无限大
for(int j=1;j<=q;j++)
{
st[i][j][0][0]=a[i][j];
st[i][j][0][1]=a[i][j];
}
for(int len=1;(1 << len)<=n+1;len++)
{
for(int j=0;j<=n-(1 << len)+1;j++)
{
st[i][j][len][0]=min(st[i][j][len-1][0],st[i][j+(1 << len)-1][len-1][1]);
st[i][j+(1 << len)-1][len][1]=min(st[i][j][len-1][0],st[i][j+(1 << len)-1][len-1][1]);
}
}
}
for(int i=0;i<=2;i++)
{
for(int x=0;x<=q;x++)
{
for(int y=0;y<=q;y++)
{
dp[0][x][y][i]=LLM;
dp[1][x][y][i]=LLM;
upd[0][x][y][i]=-305;
upd[1][x][y][i]=-305;
}
//状态初始化(DP的赋值在实际应用里是无效的,但是可以用来调试,如果转移顺序有问题,结果会变成1e16+1
}
}
dp[0][0][0][0]=0;
dp[0][0][0][1]=0;
dp[0][0][0][2]=0;
upd[0][0][0][0]=0;
upd[0][0][0][1]=0;
upd[0][0][0][2]=0;//对合理值进行初始化
las=1;//上一次执行后电梯的位置
lasi=0;//上一次执行任务的那一天
laslasi=0;//上上次执行任务的那一天
//之所以有laslasi这个变量,是因为lasi本身就是隐藏在i里面的,所以下面的x和y只需要到laslasi就行了
for(int i=0;i<q;i++)
{
if(li[i+1].first==LLM)
{
for(int x=0;x<=laslasi;x++)
{
if(li[x].first==LLM)
{
continue;
}//防止调用没有任务的一天
for(int y=0;y<=laslasi;y++)
{
if(li[y].first==LLM)
{
continue;
}
for(int e=0;e<=2;e++)
{
if(upd[i%2][x][y][e]<i)
{
continue;
}//检查是否为合理(及时更新)的值
up(i+1,x,y,e,dp[i%2][x][y][e]);
}
}
}
}else{
for(int x=0;x<=laslasi;x++)
{
if(li[x].first==LLM)
{
continue;
}
for(int y=0;y<=laslasi;y++)
{
if(li[y].first==LLM)
{
continue;
}
for(int e=0;e<=2;e++)
{
if(upd[i%2][x][y][e]<i)
{
continue;
}
up(i+1,x,y,e,dp[i%2][x][y][e]+mi(lasi,i+1,e)*abs(las-li[i+1].first)+abs(li[i+1].first-li[i+1].second)*a[e][i+1]);
up(i+1,lasi,x,(e+2)%3,dp[i%2][x][y][e]+mi(y,i+1,(e+2)%3)*abs(li[y].second-li[i+1].first)+a[(e+2)%3][i+1]*abs(li[i+1].first-li[i+1].second));
up(i+1,y,lasi,(e+1)%3,dp[i%2][x][y][e]+mi(x,i+1,(e+1)%3)*abs(li[x].second-li[i+1].first)+a[(e+1)%3][i+1]*abs(li[i+1].first-li[i+1].second));
//dp的第四维其实还决定着前两维的信息
//第四维的电梯记为e号电梯(e=0,1,2)
//则第二维是第(e+1)%3号电梯上一次执行任务的那一天
//第三维是第(e+2)%3号电梯上一次执行任务的那一天
//顺次转移就有了如上的dp式子
}
}
}
laslasi=lasi;
lasi=i+1;
las=li[i+1].second;
}
}
for(int x=0;x<q;x++)
{
for(int y=0;y<q;y++)
{
for(int e=0;e<=2;e++)
{
if(upd[q%2][x][y][e]==q)
{
ans=min(ans,dp[q%2][x][y][e]);
}
}
}
}
write(ans,true);
return 0;
}