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;}
阅读全文
0 0
- poj3467(维护前缀长度)
- 前缀和维护
- MySQL前缀索引长度方法
- POJ3467 Cross Counting
- POJ3467(预处理)
- SHU1952 Odd Pairs(维护前缀和)
- hdu 6012 维护区间前缀和
- mysql 确定前缀索引长度方法
- mysql 确定前缀索引长度方法
- mysql 确定前缀索引长度方法
- EXKMP模版:最长共同前缀长度
- hdu 4699 Editor 双栈维护最长前缀
- FZU 2129- 子序列个数 维护前缀和,思维题..
- ACdreamoj 1011(树状数组维护字符串hash前缀和)
- hdu 4699 Editor(双向链表+随便维护前缀和)
- POJ2796---Feel Good(前缀和+单调栈维护)
- Gym 100712B Rock-Paper-Scissors (前缀和维护)
- cf D. "Or" Game (前缀+后缀维护单点更新)
- 移动端(安卓、IOS)请求Java服务器时的接受数据问题
- Android Media (Audio) Framework Analyse
- Linux学习篇第三章之~postfix & mariadb
- 用你的 ESP32 做一个音乐电台
- 服务
- poj3467(维护前缀长度)
- LeetCoder 26. Remove Duplicates from Sorted Array
- Spring返回xml或json
- Spring返回xml或json
- 使用Imagenet VGG-19模型进行图片识别
- 字节,字符,Unicode,utf-32,utf-16,utf-8,ASCII的含义
- 详解KVC
- Android判断当前应用程序处于前台还是后台的两种方法
- git基础