C. Watching Fireworks is Fun (monotonic queue optimization dp)

Topic portal

The meaning of the question: You have m firework shows on a street of length n, which are staged at t[i]. Suppose you are standing at position x, and you watch the i-th firework show, you can get b[i ]-abs(a[i]-x) is the happiness value (you can’t help but watch it!), and then you can move d units of length at every moment. At the beginning you can be in any position and can’t walk out of the street. Ask how much you can get Happiness value? (May be negative).

Data range:
1 ≤ n ≤ 150000; 1 ≤ m ≤ 300; 1 ≤ d ≤ n 1 ≤ n ≤ 150000; 1 ≤ m ≤ 300; 1 ≤ d ≤ n1n150000;1m300;1dn
1   ≤   a i   ≤   n ; 1   ≤   b i   ≤   1 0 9 ; 1   ≤   t i   ≤   1 0 9 1 ≤ a_i ≤ n; 1 ≤ b_i ≤ 10^9; 1 ≤ t_i ≤ 10^9 1ain;1bi109;1ti109
Ensure that t[i] is given from small to large (seems like a useless condition, just sort it)

Solution: Seeing this data range, we can definitely think of using f [i] [j] f[i][j]f [ i ] [ j ] means that you are standing at position j watching the maximum value that can be obtained by watching the i-th firework, then in the end our answer ismax (f [m] [j]), j ∈ (1, n ) max(f[m][j]), j∈(1,n)max(f[m][j])j(1,n)

However, we can know that the i-th viewing of fireworks will only be affected by the i-1th time, so we can optimize the one-dimensional space, that is, the formula f [j] = max (f [k]) + b [i] − abs (a [i] − j), (k ∈ (max (1, j − (t [i] − t [i − 1]) ∗ d), min (n, j + (t [ i] − t [i − 1]) ∗ d))) f[j]=max(f[k])+b[i]-abs(a[i]-j),(k∈(max(1 ,j-(t[i]-t[i-1])*d),min(n,j+(t[i]-t[i-1])*d)))f[j]=max(f[k])+b[i]abs(a[i]j),(k(max(1,j(t[i]t[i1])d),m i n ( n ,j+(t[i]t[i1])d)))

Isn't this to maintain an RMQ, each time the maximum value in the interval k is asked

If we use the line segment tree to maintain RMQ, the complexity of this problem is O (nmlog (n)) O(nmlog(n))O ( n m l o g ( n ) ) , unfortunately timed out

But we found that when we traverse the streets, the information that has been used before and cannot be used in the future can be discarded. This can use monotonic queues to maintain the best value of our interval (sliding window).

Code:

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
//#define int long long
#define pii pair<int,int>
#define ull unsigned long long
#define pdd pair<double,double>
#define lowbit(x) x&-x
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    
    
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=150000+1500;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const double eps=1e-6;
const double PI=acos(-1);
int a[N],b[N],c[N];
ll f[2][N],q[N];
signed main()
{
    
    
    int n=read(),m=read(),d=read();
    for(int i=1; i<=m; i++)
    {
    
    
        a[i]=read();
        b[i]=read();
        c[i]=read();
    }
    int fg=0,t=c[1];
    for(int i=1; i<=m; i++)
    {
    
    
        int l=0,r=0,k=1;
        if(i==1)
        {
    
    
            for(int j=1; j<=n; j++)
                f[fg][j]=b[i]-abs(a[i]-j);//刚开始,直接给值
        }
        else
        {
    
    
            for(int j=1; j<=n; j++)
            {
    
    
                while(k<=n&&k<=j+1LL*(c[i]-c[i-1])*d)//k在合法范围内
                {
    
    
                    while(l<r&&f[fg^1][k]>=f[fg^1][q[r-1]])
                    //后面到的比前面的更大,就一定更优,直接插队就行了
                        r--;
                    q[r++]=k++;
                }
                while(l<r&&j-1LL*(c[i]-c[i-1])*d>q[l])
                //已经超出范围的无用信息就直接删去,最后队列首部就是当前最优的状态
                    l++;
                f[fg][j]=f[fg^1][q[l]]+b[i]-abs(a[i]-j);
            }
        }
        fg^=1;
    }
    ll res=-1e18;
    for(int i=1;i<=n;i++)
        res=max(res,f[fg^1][i]);
    cout<<res<<endl;
    return 0;
}

Guess you like

Origin blog.csdn.net/Joker_He/article/details/109302098