您的位置:首页 > 其它

Educational Codeforces Round 8 E - Zbazi in Zeydabad

2016-04-01 13:26 351 查看
http://codeforces.com/contest/628/problem/E

L[i][j] 表示(i,j)左边连续的‘z’个数

R[i][j] 表示右边

D[i][j] 从左下,向右上 ,连续‘z’的个数

每次求 以 (i,j) 为左上角顶点的 ‘z’的个数:

另 k = min(L[i][j],D[i][j]); 那么 以 (i,j) 为左上角顶点的 ‘z’的个数 最多为k个。

具体有几个? 从(i,j) 向左下角延伸(延伸距离不超过k),得到的每个点(x,y),如果y+R[x][y] > j 则是一个可行解

用树状数组维护 y+R[x][y] > j 的个数。 由于对角线上的点x+y恒定且唯一,因此以x+y 作为某对角线所对应树状数组的编号

#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#include<ctime>
using namespace std;
void fre(){freopen("t.txt","r",stdin);}
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
#define ls o<<1
#define rs o<<1|1
#define MS(x,y) memset(x,y,sizeof(x))
#define debug(x) printf("%d",x);
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
const int INF = 1<<30;
const int MAXN = 105;
const double eps = 1e-8;
const double pi = acos(-1.0);
const LL M = 1e9+7;

int n,m,L[3005][3005],R[3005][3005],D[3005][3005],a[6006][3005];
char mp[3005][3005];
LL ans;
void add(int y,int x)
{
while(x <= 3000)
{
a[y][x]+=1;
x+= x&(-x);
}
}
int query(int y,int x)
{
int ret = 0;
while(x > 0)
{
ret+= a[y][x];
x-=x&(-x);
}
return ret;
}
void init()
{
int i,j;
for(i = 1; i <= n; ++i)
for(j = 1; j <= m; ++j)
if(mp[i][j] == 'z') L[i][j] = L[i][j-1]+1;
else L[i][j] = 0;

for(i = 1; i <= n; ++i)
for(j = m; j > 0; --j)
if(mp[i][j] == 'z') R[i][j] = R[i][j+1]+1;
else R[i][j] = 0;

for(i = n; i > 0; --i)
for(j = 1; j <= m; ++j)
if(mp[i][j] == 'z') D[i][j] = D[i+1][j-1]+1;
else D[i][j] = 0;
}
void solve()
{
int i,j,k,x,y;
for(j = m; j > 0; --j)
{
for(i = 1; i <= n; ++i)//维护树状数组
{
if(L[i][j+1] || mp[i][j] != 'z') continue;
for(y = j; y >= j-L[i][j]+1; --y) add(i+y,y);
}
for(i = 1; i <= n; ++i)//查询
{
if(mp[i][j] != 'z') continue;
k = min(L[i][j],D[i][j]);
ans+=query(i+j,j) - query(i+j,j-k);
}
}
}
int main()
{
//fre();
ans = 0;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; ++i)
scanf("%s",mp[i]+1);
init();
solve();
printf("%I64d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: