poj3467(维护前缀长度)

来源:互联网 发布:怎么查询网络稳定 编辑:程序博客网 时间:2024/06/03 09:36

链接:点击打开链接

题意:给定一个n*m的矩阵,每个点有一个权值,现在有两种操作,一种是将其中任何一个元素改成1~c中的任意值,另一种是输出权值u按十字计数的种数(具体看样例)

代码:

#include <queue>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;int n,m;int num[105],s[105][105];int le[105][105],re[105][105],up[105][105],dw[105][105];void cal(int x,int y,int id){    int i;    if(id==1){        for(i=x+1;i<=n;i++){            if(s[i][y]==s[x][y])            dw[x][y]++;            else            break;        }    }    else if(id==2){        for(i=x-1;i>=1;i--){            if(s[i][y]==s[x][y])            up[x][y]++;            else            break;        }    }    else if(id==3){        for(i=y-1;i>=1;i--){            if(s[x][i]==s[x][y])            le[x][y]++;            else            break;        }    }    else{        for(i=y+1;i<=m;i++){            if(s[x][i]==s[x][y])            re[x][y]++;            else            break;        }    }}void update(int x,int y,int op){                //每个点分三种情况讨论一下即可    int i;    if(s[x][y]==op)    return;    for(i=1;i<=x-1;i++){        if(dw[i][y]<x-i-1)        continue;        else if(dw[i][y]==x-i-1){            if(s[i][y]==op){                dw[i][y]++;                if(x+1<=n&&s[x+1][y]==s[i][y])                dw[i][y]+=(dw[x+1][y]+1);            }        }        else        dw[i][y]=x-i-1;    }    for(i=n;i>=x+1;i--){        if(up[i][y]<i-x-1)        continue;        else if(up[i][y]==i-x-1){            if(s[i][y]==op){                up[i][y]++;                if(x-1>=1&&s[x-1][y]==s[i][y])                up[i][y]+=(up[x-1][y]+1);            }        }        else        up[i][y]=i-x-1;    }    for(i=1;i<=y-1;i++){        if(re[x][i]<y-i-1)        continue;        else if(re[x][i]==y-i-1){            if(s[x][i]==op){                re[x][i]++;                if(y+1<=m&&s[x][y+1]==s[x][i])                re[x][i]+=(re[x][y+1]+1);            }        }        else        re[x][i]=y-i-1;    }    for(i=m;i>=y+1;i--){        if(le[x][i]<i-y-1)        continue;        else if(le[x][i]==i-y-1){            if(s[x][i]==op){                le[x][i]++;                if(y-1>=1&&s[x][y-1]==s[x][i])                le[x][i]+=(le[x][y-1]+1);            }        }        else        le[x][i]=i-y-1;    }    s[x][y]=op;    up[x][y]=dw[x][y]=le[x][y]=re[x][y]=0;    for(i=1;i<=4;i++)    cal(x,y,i);}int main(){    char ch;    int c,q,i,j,u,v,id,op;    while(scanf("%d%d%d%d",&n,&m,&c,&q)!=EOF){        for(i=1;i<=n;i++)                       //直接维护每个点向四个方向的连续长度        for(j=1;j<=m;j++)                       //当改任何一个值时,可以每个点直接O(1)        scanf("%d",&s[i][j]);                   //进行更改,因此复杂度就为O(Q*2*(n+m))        memset(le,0,sizeof(le));        memset(re,0,sizeof(re));        memset(up,0,sizeof(up));        memset(dw,0,sizeof(dw));        memset(num,0,sizeof(num));        for(i=1;i<=n;i++){                      //直接维护出每个点四个方向的值            for(j=1;j<=m;j++){                for(id=1;id<=4;id++)                cal(i,j,id);            }        }        for(i=1;i<=n;i++)        for(j=1;j<=m;j++)                       //四个方向最小值即为每个点的个数        num[s[i][j]]+=min(min(up[i][j],dw[i][j]),min(le[i][j],re[i][j]));        while(q--){            cin>>ch;            if(ch=='Q'){                scanf("%d",&u);                printf("%d\n",num[u]);            }            else{                scanf("%d%d%d",&u,&v,&op);                for(j=1;j<=m;j++)               //询问时可以先将原来的值都减掉                num[s[u][j]]-=min(min(up[u][j],dw[u][j]),min(le[u][j],re[u][j]));                for(i=1;i<=n;i++){              //当更新后再重新加回来                    if(i==u)                    continue;                    num[s[i][v]]-=min(min(up[i][v],dw[i][v]),min(le[i][v],re[i][v]));                }                update(u,v,op);                for(j=1;j<=m;j++)                num[s[u][j]]+=min(min(up[u][j],dw[u][j]),min(le[u][j],re[u][j]));                for(i=1;i<=n;i++){                    if(i==u)                    continue;                    num[s[i][v]]+=min(min(up[i][v],dw[i][v]),min(le[i][v],re[i][v]));                }            }        }    }    return 0;}