zoukankan      html  css  js  c++  java
  • 【Luogu】P2254瑰丽华尔兹(堆优化DP)

      题目链接

      我也不知道为什么脑子一抽就想了个堆优化……然后贼慢……

      因为上午听不懂wys的电音专场(快速傅立叶变换),然后就做了这么一道题。

      首先朴素DP很sb都能秒出。就是枚举时刻、位置(两维)然后转移。

      观察发现这是O(TNM)的,可以通过50%的数据。

      然后……(喂题目提示得太明显了吧)发现时间段只有200个,跟50%的T是一样的

      这简直就是明说:“快往O(KNM)上想!”

      然后我就不知道为啥想了个O(KNMlogn),qwq。

      枚举时刻改为枚举时间段,每个时间段枚举位置用堆优化(其实应该用单调队列)转移得出答案。

      虽然题目水+我的方法慢+我是sb+实现方法诡异+调了很久,1A还是很高兴的。

      (实现方法智障……可以当成锻炼代码能力嘛qwq)

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #define maxn 205
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Node{
        int dat,pos;
        bool operator <(const Node a)const{
            return dat>a.dat;
        }
        bool operator <=(const Node a)const{
            return dat>=a.dat;
        }
    };
    
    struct Heap{
        Node heap[505];int size;
        Heap(){ size=0;}
        inline void push(Node x){
            heap[++size]=x;
            register int i=size,k;
            while(i>1){
                k=i>>1;
                if(heap[k]<=heap[i])    return;
                swap(heap[i],heap[k]);
                i=k;
            }
            return;
        }
        inline bool empty(){    return !size;    }
        inline Node top(){    return heap[1];    }
        inline void clear(){size=0;}
        inline void pop(){
            heap[1]=heap[size--];
            register int i=1,k;
            while((i<<1)<=size){
                k=i<<1;
                if(k<size&&heap[k|1]<heap[k])    k|=1;
                if(heap[i]<=heap[k])    return;
                swap(heap[i],heap[k]);
                i=k;
            }
        }
    };
    
    Heap s[maxn];
    
    int last,now=1;
    int f[maxn][maxn][2];
    char mp[maxn][maxn];
    
    struct Line{
        int from,to,dir;
        bool operator <(const Line a)const{    return from<a.from;    }
    }q[maxn];
    
    int main(){
        int n=read(),m=read(),sx=read(),sy=read(),e=read();
        for(int i=1;i<=n;++i)    scanf("%s",mp[i]+1);
        for(int i=1;i<=e;++i)    q[i]=(Line){read(),read(),read()};
        sort(q+1,q+e+1);
        memset(f,-127/3,sizeof(f));
        f[sx][sy][last]=0;
        for(int i=1;i<=e;++i){
            int from=q[i].from,to=q[i].to,dir=q[i].dir;
            if(dir<3)
                for(int j=1;j<=m;++j){
                    s[j].clear();
                    if(dir==1){
                        int cnt=0;
                        for(int k=n;k;--k){
                            f[k][j][now]=-100000000;
                            cnt++;
                            if(mp[k][j]=='x'){
                                s[j].clear();
                                continue;
                            }
                            if(s[j].empty()){
                                f[k][j][now]=f[k][j][last];
                                s[j].push((Node){f[k][j][last]-cnt,k}); 
                                continue;
                            }
                            Node ret=s[j].top();
                            while((!s[j].empty())&&ret.pos-k>to-from+1){
                                s[j].pop();
                                ret=s[j].top();
                            }
                            if(s[j].empty()){
                                f[k][j][now]=f[k][j][last];
                                s[j].push((Node){f[k][j][last]-cnt,k});
                                continue;
                            }
                            //printf("%d %d %d %d
    ",k,j,ret.pos,f[ret.pos][j][last]+ret.pos-k);
                            f[k][j][now]=max(f[k][j][last],f[ret.pos][j][last]+ret.pos-k);
                            s[j].push((Node){f[k][j][last]-cnt,k});
                        }
                    }
                    else{
                        int cnt=0;
                        for(int k=1;k<=n;++k){
                            f[k][j][now]=-100000000;
                            cnt++;
                            if(mp[k][j]=='x'){
                                s[j].clear();
                                continue;
                            }
                            if(s[j].empty()){
                                f[k][j][now]=f[k][j][last];
                                s[j].push((Node){f[k][j][last]-cnt,k});
                                continue;
                            }
                            Node ret=s[j].top();
                            while((!s[j].empty())&&k-ret.pos>to-from+1){
                                s[j].pop();
                                ret=s[j].top();
                            }
                            if(s[j].empty()){
                                f[k][j][now]=f[k][j][last];
                                s[j].push((Node){f[k][j][last]-cnt,k});
                                continue;
                            }
                            f[k][j][now]=max(f[k][j][last],f[ret.pos][j][last]+k-ret.pos);
                            s[j].push((Node){f[k][j][last]-cnt,k});
                        }
                    }
                }
            else
                for(int j=1;j<=n;++j){
                    s[j].clear();
                    if(dir==4){
                        int cnt=0;
                        for(int k=1;k<=m;++k){
                            f[j][k][now]=-100000000;
                            cnt++;
                            if(mp[j][k]=='x'){
                                s[j].clear();
                                continue;
                            }
                            if(s[j].empty()){
                                f[j][k][now]=f[j][k][last];
                                s[j].push((Node){f[j][k][last]-cnt,k});
                                continue;
                            }
                            Node ret=s[j].top();
                            while((!s[j].empty())&&k-ret.pos>to-from+1){
                                s[j].pop();
                                ret=s[j].top();
                            }
                            if(s[j].empty()){
                                f[j][k][now]=f[j][k][last];
                                s[j].push((Node){f[j][k][last]-cnt,k});
                                continue;
                            }
                            //printf("%d %d %d
    ",j,k,f[j][ret.pos][last]+k-ret.pos);
                            f[j][k][now]=max(f[j][k][last],f[j][ret.pos][last]+k-ret.pos);
                            s[j].push((Node){f[j][k][last]-cnt,k});
                        }
                    }
                    else{
                        int cnt=0;
                        for(int k=m;k;--k){
                            f[j][k][now]=-100000000;
                            cnt++;
                            if(mp[j][k]=='x'){
                                s[j].clear();
                                continue;
                            }
                            if(s[j].empty()){
                                f[j][k][now]=f[j][k][last];
                                s[j].push((Node){f[j][k][last]-cnt,k});
                                continue;
                            }
                            Node ret=s[j].top();
                            while((!s[j].empty())&&ret.pos-k>to-from+1){
                                s[j].pop();
                                ret=s[j].top();
                            }
                            if(s[j].empty()){
                                f[j][k][now]=f[j][k][last];
                                s[j].push((Node){f[j][k][last]-cnt,k});
                                continue;
                            }
                            //printf("%d %d %d
    ",j,k,f[j][ret.pos][last]+ret.pos-k);
                            f[j][k][now]=max(f[j][k][last],f[j][ret.pos][last]+ret.pos-k);
                            s[j].push((Node){f[j][k][last]-cnt,k});
                        }
                    }
                }
            swap(now,last);
        }
        int ans=0;
        for(int i=1;i<=n;++i)    
            for(int j=1;j<=m;++j)    ans=max(ans,f[i][j][last]);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Codeforces Round #649 (Div. 2) D. Ehab's Last Corollary
    Educational Codeforces Round 89 (Rated for Div. 2) E. Two Arrays
    Educational Codeforces Round 89 (Rated for Div. 2) D. Two Divisors
    Codeforces Round #647 (Div. 2) E. Johnny and Grandmaster
    Codeforces Round #647 (Div. 2) F. Johnny and Megan's Necklace
    Codeforces Round #648 (Div. 2) G. Secure Password
    Codeforces Round #646 (Div. 2) F. Rotating Substrings
    C++STL常见用法
    各类学习慕课(不定期更新
    高阶等差数列
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8421736.html
Copyright © 2011-2022 走看看