原本以为昨天老师考的已经够难了,弄了那么多的状压DP但是今天老师好像比昨天还狠,弄的状压题比昨天还多,还难,还额外弄了两道没做过的额外的题,还弄了两道tarjan......

暑期集训第四天(6-25)题解及总结

 

 

 暑期集训第四天(6-25)题解及总结

 

 

暑期集训第四天(6-25)题解及总结

 

 

 这道题虽然是第一道题,但却是我最后改的(考试的时候没做出来),其实看完题解后觉得这道题也没有那么难,看来以后这类类似的对dp式子进行分析的题还要多做.

分析: 读完题目后考虑递推公式,dp[i][j]=max(dp[i-1][k])+b[i]-|a[i]-j|在这个式子之中b[i]的值是已经确定的,i一旦确定a[i]也就没有问题了,所以我们把目光聚焦在d[i][j]上我们当然可以用一个多重循环来解决这个问题,但是根据题目中的数据范围这样写是一定会超时的,但是假设我们最后站在j点,设h=(t1-t2)*d,那么我们的k的活动范围就在j+h和j-h之间,区间移动求一个最值,我们想到来使用单调队列来进行优化就可以了,dp如果硬开是开不下的,但是只和上一行的状态有关,所以用滚动数组优化.

 

 1 #include<cstring>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<queue>
 5 typedef long long ll;
 6 using namespace std;
 7 const int maxn=15e4+5;
 8 ll dp[2][maxn];
 9 void Solve(){
10     int n,m,d;
11     scanf("%d%d%d",&n,&m,&d);
12     int t0=1,k=0; 
13     while(m--){
14         int a,t,b;
15         scanf("%d%d%d",&a,&b,&t);
16         ll h=(ll)1*(t-t0)*d;
17         h=min(h,(ll)n);
18         t0=t;
19         k=!k;
20         deque<int>q;//单调队列 
21         for(int i=1,j=1;i<=n;++i){
22             for(;j<=i+h&&j<=n;++j){
23                 while(!q.empty()&&dp[!k][q.back()]<=dp[!k][j]) q.pop_back();
24                 q.push_back(j);
25             }
26             while(!q.empty()&&q.front()<i-h) q.pop_front();
27             dp[k][i]=dp[!k][q.front()]+b-abs(a-i);
28         }
29     }
30     ll ans=dp[k][1];
31     for(int i=2;i<=n;++i)
32         ans=max(ans,dp[k][i]);
33     printf("%lld\n",ans);
34 }
35 int main(){
36     //freopen("a.in","r",stdin);
37     Solve();
38     return 0;
39 }
Watching Fireworks is Fun

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-19
猜你喜欢
  • 2022-02-05
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案