bzoj 1499: [NOI2005]瑰丽华尔兹

其实这是个论文题我会乱说?

我大概是我见过的最简单的NOI题了吧

然而并没有用论文里的的方法(虽然是黑科技但是好麻烦啊)

这个东西嘛,很明显每次转移都是区域化的。

然后单调队列维护乱搞一下

代码写得好丑QAQ没治了

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int inf=1e9;
int f[2][205][205],up[205][205][4];
int q[205],h,t,now,last;
int n,m;
char mp[205][205]; 
void push(int x){
    while(h<=t&&q[t]<x)t--;
    q[++t]=x;
}
void pop(int x){
    if(q[h]==x)h++;
}
void solve1(int l){
    for(int j=1;j<=m;j++){
        h=0;t=-1;
        int d=0,ed=n;
        for(int i=n;i>=1;i--){
            d--;push(f[last][i][j]+d);
            if(mp[i][j]=='x'){
                f[now][i][j]=-inf;
                continue;
            }
            int tmp=min(up[i][j][0],i+l);
            while(ed>tmp){
                pop(f[last][ed][j]+d+ed-i);
                ed--;
            }
            f[now][i][j]=q[h]-d;
        }
    }
}
void solve2(int l){
    for(int j=1;j<=m;j++){
        h=0;t=-1;
        int d=0,ed=1;
        for(int i=1;i<=n;i++){
            d--;push(f[last][i][j]+d);
            if(mp[i][j]=='x'){
                f[now][i][j]=-inf;
                continue;
            }
            int tmp=max(up[i][j][1],i-l);
            while(ed<tmp){
                pop(f[last][ed][j]+d+i-ed);
                ed++;
            }
            f[now][i][j]=q[h]-d;
        }
    }
}
void solve3(int l){
    for(int i=1;i<=n;i++){
        h=0;t=-1;
        int d=0,ed=m;
        for(int j=m;j>=1;j--){
            d--;push(f[last][i][j]+d);
            if(mp[i][j]=='x'){
                f[now][i][j]=-inf;
                continue;
            }
            int tmp=min(up[i][j][2],j+l);
            while(ed>tmp){
                pop(f[last][i][ed]+d+ed-j);
                ed--;
            }
            f[now][i][j]=q[h]-d;
        }
    }
}
void solve4(int l){
    for(int i=1;i<=n;i++){
        h=0;t=-1;
        int d=0,ed=1;
        for(int j=1;j<=m;j++){
            d--;push(f[last][i][j]+d);
            if(mp[i][j]=='x'){
                f[now][i][j]=-inf;
                continue;
            }
            int tmp=max(j-l,up[i][j][3]);
            while(ed<tmp){
                pop(f[last][i][ed]+d+j-ed);
                ed++;
            }
            f[now][i][j]=q[h]-d;
        }
    }
}
int main(){
    //freopen("a.in","r",stdin);
    int x,y;
    scanf("%d%d%d%d",&n,&m,&x,&y);
    now=0;last=1;
    memset(f[now],-0x3f,sizeof(f[now]));
    f[now][x][y]=0;
    int k;scanf("%d",&k);
    for(int i=1;i<=n;i++)
    scanf("%s",mp[i]+1);
    for(int i=1;i<=n;i++){
        up[i][m+1][2]=m;
        for(int j=m;j>=1;j--)
        if(mp[i][j]=='x')up[i][j][2]=j-1;
        else up[i][j][2]=up[i][j+1][2];
        up[i][0][3]=1;
        for(int j=1;j<m;j++)
        if(mp[i][j]=='x')up[i][j][3]=j+1;
        else up[i][j][3]=up[i][j-1][3];
    }
    for(int j=1;j<=m;j++){
        up[n+1][j][0]=n;
        for(int i=n;i>=1;i--)
        if(mp[i][j]=='x')up[i][j][0]=i-1;
        else up[i][j][0]=up[i+1][j][0];
        up[0][j][1]=1;
        for(int i=1;i<=n;i++)
        if(mp[i][j]=='x')up[i][j][1]=i+1;
        else up[i][j][1]=up[i-1][j][1];
    }
    while(k--){
        int si,ti,di;scanf("%d%d%d",&si,&ti,&di);
        now^=1;last^=1;
        if(di==1)solve1(ti-si+1);
        else if(di==2)solve2(ti-si+1);
        else if(di==3)solve3(ti-si+1);
        else solve4(ti-si+1);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    ans=max(ans,f[now][i][j]);
    printf("%d\n",ans);
    return 0;
}

卧槽,下一篇论文讲的就是这个Σ( ° △ °|||)︴

好吧其实我想说的是我没用那个诡异的指针运算

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值