HDU 5749 Colmerauer(单调栈+推公式)
2016-07-24 16:20
387 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5749
题意:给你一个n*m的矩形然后求W=(∑a=1n∑b=1ma⋅b⋅S(a,b)) mod 232,S(a,b)表示所有大小是a*b的子矩阵的鞍点的值的和。
题解:鞍点是在行里唯一最小,列里唯一最大,所以先单调栈一下,有点麻烦,细心点写就行,然后就是求这个点的贡献,等于就是这个点在一个矩形里,求这个矩形里,其他所有包含这个点的子矩形的面积和。
有两种方法,第一种是容斥,就是算在长a宽b的矩形里,所有子矩形的面积,然后减去边上不包含这个点的四块里的所有子矩形的面积,最后加上4个角上的。
长a宽b的矩形里所有子矩形的面积是
长为1的所有矩形面积:a×1×(b×1+(b−1)×2+⋯+1×b)
后面括号里的求和是∑i=1b(b+1−i)×i
展开得到∑i=1b(b+1)i−i×i
求和就是b(b+1)(b+2)6
所以长a宽b的矩形里面所有子矩形的面积就是ab(a+1)(b+1)(a+2)(b+2)36
这是第一种容斥的方法。
第二种直接算的方法就是假设这个点在矩形里,距离上左下右的距离分别 是a,b,c,d,公式就是∑i=0a∑j=0b∑k=0c∑h=0d(i+k+1)∗(j+h+1)
然后直接推导就得(a+1)(c+1)(a+c+2)2∗(b+1)(d+1)(b+d+2)2
方法1:
方法2:
题意:给你一个n*m的矩形然后求W=(∑a=1n∑b=1ma⋅b⋅S(a,b)) mod 232,S(a,b)表示所有大小是a*b的子矩阵的鞍点的值的和。
题解:鞍点是在行里唯一最小,列里唯一最大,所以先单调栈一下,有点麻烦,细心点写就行,然后就是求这个点的贡献,等于就是这个点在一个矩形里,求这个矩形里,其他所有包含这个点的子矩形的面积和。
有两种方法,第一种是容斥,就是算在长a宽b的矩形里,所有子矩形的面积,然后减去边上不包含这个点的四块里的所有子矩形的面积,最后加上4个角上的。
长a宽b的矩形里所有子矩形的面积是
长为1的所有矩形面积:a×1×(b×1+(b−1)×2+⋯+1×b)
后面括号里的求和是∑i=1b(b+1−i)×i
展开得到∑i=1b(b+1)i−i×i
求和就是b(b+1)(b+2)6
所以长a宽b的矩形里面所有子矩形的面积就是ab(a+1)(b+1)(a+2)(b+2)36
这是第一种容斥的方法。
第二种直接算的方法就是假设这个点在矩形里,距离上左下右的距离分别 是a,b,c,d,公式就是∑i=0a∑j=0b∑k=0c∑h=0d(i+k+1)∗(j+h+1)
然后直接推导就得(a+1)(c+1)(a+c+2)2∗(b+1)(d+1)(b+d+2)2
方法1:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 1005 #define MAXN 1000005 #define maxnode 15 #define sigma_size 30 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,int> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; const double pi = acos(-1.0); const double inf = 1e18; const double eps = 1e-4; const LL mod = 1e9+7; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ int a[MAX][MAX]; int st[MAX]; int l[MAX][MAX],r[MAX][MAX],up[MAX][MAX],down[MAX][MAX]; unsigned rong(unsigned a,unsigned b){ return (b*(b+1)*(b+2)/6)*(a*(a+1)*(a+2)/6); } int main(){ //freopen("in.txt","r",stdin); int t; cin>>t; while(t--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); l[i][j]=1; r[i][j]=m; up[i][j]=1; down[i][j]=n; } } for(int i=1;i<=n;i++){ int top=0; st[++top]=0; for(int j=1;j<=m;j++){ while(top>1&&a[i][st[top]]>a[i][j]){ r[i][st[top]]=min(j-1,r[i][st[top]]); top--; } if(top>1&&a[i][st[top]]==a[i][j]) l[i][j]=max(l[i][j],st[top]+1); while(top>1&&a[i][st[top]]==a[i][j]){ r[i][st[top]]=min(j-1,r[i][st[top]]); top--; } l[i][j]=max(l[i][j],st[top]+1); st[++top]=j; } } for(int j=1;j<=m;j++){ int top=0; st[++top]=0; for(int i=1;i<=n;i++){ while(top>1&&a[st[top]][j]<a[i][j]){ down[st[top]][j]=min(down[st[top]][j],i-1); top--; } if(top>1&&a[st[top]][j]==a[i][j]) up[i][j]=max(up[i][j],st[top]+1); while(top>1&&a[st[top]][j]==a[i][j]){ down[st[top]][j]=min(down[st[top]][j],i-1); top--; } up[i][j]=max(up[i][j],st[top]+1); st[++top]=i; } } unsigned ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ unsigned ret=rong(r[i][j]-l[i][j]+1,down[i][j]-up[i][j]+1); ret-=rong(r[i][j]-j,down[i][j]-up[i][j]+1); ret-=rong(j-l[i][j],down[i][j]-up[i][j]+1); ret-=rong(r[i][j]-l[i][j]+1,i-up[i][j]); ret-=rong(r[i][j]-l[i][j]+1,down[i][j]-i); ret+=rong(r[i][j]-j,i-up[i][j]); ret+=rong(r[i][j]-j,down[i][j]-i); ret+=rong(j-l[i][j],i-up[i][j]); ret+=rong(j-l[i][j],down[i][j]-i); unsigned tmp=a[i][j]; ans+=ret*tmp; } } cout<<ans<<endl; } return 0; }
方法2:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 1005 #define MAXN 1000005 #define maxnode 15 #define sigma_size 30 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,int> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; const double pi = acos(-1.0); const double inf = 1e18; const double eps = 1e-4; const LL mod = 1e9+7; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ int a[MAX][MAX]; int st[MAX]; int l[MAX][MAX],r[MAX][MAX],up[MAX][MAX],down[MAX][MAX]; unsigned cal(unsigned a,unsigned b,unsigned c,unsigned d){ return ((a+1)*(c+1)*(a+c+2)/2)*((b+1)*(d+1)*(b+d+2)/2); } int main(){ //freopen("in.txt","r",stdin); int t; cin>>t; while(t--){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); l[i][j]=1; r[i][j]=m; up[i][j]=1; down[i][j]=n; } } for(int i=1;i<=n;i++){ int top=0; st[++top]=0; for(int j=1;j<=m;j++){ while(top>1&&a[i][st[top]]>a[i][j]){ r[i][st[top]]=min(j-1,r[i][st[top]]); top--; } if(top>1&&a[i][st[top]]==a[i][j]) l[i][j]=max(l[i][j],st[top]+1); while(top>1&&a[i][st[top]]==a[i][j]){ r[i][st[top]]=min(j-1,r[i][st[top]]); top--; } l[i][j]=max(l[i][j],st[top]+1); st[++top]=j; } } for(int j=1;j<=m;j++){ int top=0; st[++top]=0; for(int i=1;i<=n;i++){ while(top>1&&a[st[top]][j]<a[i][j]){ down[st[top]][j]=min(down[st[top]][j],i-1); top--; } if(top>1&&a[st[top]][j]==a[i][j]) up[i][j]=max(up[i][j],st[top]+1); while(top>1&&a[st[top]][j]==a[i][j]){ down[st[top]][j]=min(down[st[top]][j],i-1); top--; } up[i][j]=max(up[i][j],st[top]+1); st[++top]=i; } } unsigned ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ unsigned x=i-up[i][j]; unsigned y=j-l[i][j]; unsigned z=down[i][j]-i; unsigned w=r[i][j]-j; unsigned tmp=a[i][j]; ans+=cal(x,y,z,w)*tmp; } } cout<<ans<<endl; } return 0; }
相关文章推荐
- HDU 5749 Colmerauer 单调队列+暴力贡献
- JAVASE总结--05(continue、break)
- Arduino接收红外信号
- POJ 1019 Number Sequence
- codeforce 24D Broken robot—概率DP—conquersea博客
- 对数据集“dsArea”执行查询失败。 (rsErrorExecutingCommand),Query execution failed for dataset 'dsArea'. (rsErrorExecutingCommand),Manually process the TFS data warehouse and analysis services cube
- 递归搜索 ( 水题 )——A Rational Sequence ( UVA 7363 )
- poj 2524 Ubiquitous Religions [并查集]
- jeasyui扩展:combogrid实现本地数据过滤
- Vue.js - 学习笔记 (一)
- HDU 4915 Parenthese sequence
- POJ2533:Longest Ordered Subsequence(LIS)
- codeforces 145E Lucky Queries
- Hdu 5749 Colmerauer
- LIS(Longest Increasing Subsequence)最长上升子序列算法浅析
- CodeForces 427A Police Recruits (水题)
- 压缩感知重构算法之基追踪降噪(Basis Pursuit De-Noising, BPDN)
- Java中的String、StringBuilder以及StringBuffer区别
- String、StringBuffer、StringBuilder区别与联系
- SAP GUI730 PATCH15 下载