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;
    }
  • 相关阅读:
    第二阶段总结
    今日总结
    今日总结
    今日总结
    今日总结
    今日总结
    今日总结
    今日总结
    今日总结
    开学总结
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8421736.html
Copyright © 2011-2022 走看看