Dasha and Photos CodeForces - 761F (前缀优化)

大意: 给定n*m初始字符矩阵, 有k个新矩阵, 第$i$个矩阵是由初始矩阵区间赋值得到的, 求选择一个新矩阵, 使得其余新矩阵到它距离和最小.

字符集比较小, 可以考虑每次区间覆盖对每个字符的贡献. 区间覆盖转化为差分, 然后前缀和优化.

刚开始辅助数组开多了, 卡内存卡了好久. 看别人代码似乎可以再优化掉两个辅助数组.

#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<‘0‘||p>‘9‘)p=getchar();while(p>=‘0‘&&p<=‘9‘)x=x*10+p-‘0‘,p=getchar();return x;}
//head

const int M = 3e5+10, N = 1e3+10;
int n, m, k;
char s[N][N];
int l[M], l2[M], r[M], r2[M], e[M];
int c[26][N][N], d[26][N][N];
ll sum[N][N], val[26][N][N];
void upd(int c[N][N], int l, int r, int l2, int r2, int v) {
	c[l][r]+=v,c[l][r2+1]-=v,c[l2+1][r]-=v,c[l2+1][r2+1]+=v;
}
ll get(ll c[N][N], int id) {
	return c[l2[id]][r2[id]]-c[l[id]-1][r2[id]]-c[l2[id]][r[id]-1]+c[l[id]-1][r[id]-1];
}

int main() {
	scanf("%d%d%d", &n, &m, &k);
	REP(i,1,n) scanf("%s", s[i]+1);
	REP(i,1,n) REP(j,1,m) s[i][j]-=‘a‘;
	REP(i,1,k) {
		char cc;
		scanf("%d%d%d%d %c", l+i,r+i,l2+i,r2+i,&cc);
		e[i] = cc-‘a‘;
		REP(t,0,25) upd(d[t],l[i],r[i],l2[i],r2[i],-1);
		REP(t,0,25) upd(c[t],l[i],r[i],l2[i],r2[i],abs(e[i]-t));
	}
	REP(i,1,n) REP(j,1,m) {
		REP(t,0,25) {
			d[t][i][j] += d[t][i-1][j]+d[t][i][j-1]-d[t][i-1][j-1];
			c[t][i][j] += c[t][i-1][j]+c[t][i][j-1]-c[t][i-1][j-1];
			val[t][i][j] = (ll)(k+d[t][i][j])*abs(t-s[i][j])+c[t][i][j];
		}
		sum[i][j] = val[s[i][j]][i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
		REP(t,0,25) val[t][i][j]+=val[t][i-1][j]+val[t][i][j-1]-val[t][i-1][j-1];
	}
	ll ans = 1e18;
	REP(i,1,k) ans=min(ans,sum[n][m]-get(sum,i)+get(val[e[i]],i));
	printf("%lld\n", ans);
}

原文地址:https://www.cnblogs.com/uid001/p/10824711.html

时间: 2024-10-12 19:42:40

Dasha and Photos CodeForces - 761F (前缀优化)的相关文章

核发电站 (dp前缀优化)

大意: $n$个城市, $m$种核电站, 第$i$种假设要建在第$x$个城市, 必须满足$[x-i,x+i]$范围内无其他核电站, 求建核电站的方案数. 简单$dp$题, 设$dp[i][j]$为位置$i$建第$j$种核电站的方案数. 枚举上一个核电站的位置来转移, 有: $dp[i][1]=1+dp[i-2][1]+\sum\limits_{k=1}^2 dp[i-3][k]+\sum\limits_{k=1}^3dp[i-4][k]+...$ $dp[i][j]=dp[i][j-1]-\su

Codeforces Round #274 (Div. 2) E:Riding in a Lift DP + 前缀优化

题意: n,a,b,k(2?≤?n?≤?5000,1?≤?k?≤?5000,1?≤?a,?b?≤?n,a?≠?b).四个数.1到n的数,顺序排列,其实位置人在a位置而中心位置在b,人每次只能走一个点走动的距离必须小于|b?a|,人走k步之后停止,问人一共有多少种走法. 分析: 开始很容易想到一个深度优先搜索实现递归方法dfs(a, k)但k变为0就到达搜索底部,这样时间复杂度是O(nk)显然非常不好. 然后可以想到会有重算的情况,就可以加一个记忆优化把算过的(a,k)的二元组都保存下来.这样处理

Codeforces Round #427 (Div. 2) Problem C Star sky (Codeforces 835C) - 前缀和

The Cartesian coordinate system is set in the sky. There you can see n stars, the i-th has coordinates (xi, yi), a maximum brightness c, equal for all stars, and an initial brightness si (0 ≤ si ≤ c). Over time the stars twinkle. At moment 0 the i-th

Codeforces 612D 前缀和处理区间问题

传送门:http://codeforces.com/problemset/problem/612/D (转载请注明出处谢谢) 题意: 给出数字n和k,n表示接下来将输入n个在x轴上的闭区间[li,ri],找出被包含了至少k次的点,并求由这些点组成的连续区间的数目,并使该数目最小.输出该数目并将区间从左到右(x的正方向)输出. 比如样例1,给出区间[0,5],[-3,2],[3,8],那么被覆盖了至少两次的区间就是[0,2],[3,5],有两个. 解题思路: 处理区间覆盖,一上来就想到了前缀和,普

(Incomplete) Codeforces 394 (Div 2 only)

A. Dasha and Stairs 保证a,b不同时为0,而且a 和 b 的绝对值不超过1即可.(心态崩了的我强行写出一个暴力,枚举了所有的情况.) code: B. Dasha and friends 对于两个跑道,分别计算出每个片段的长度.固定第一个跑道的起点,枚举第二个跑道的起点,看两个跑道能否匹配.本题n很小,所以O(n^2)的暴力即可.既然是匹配,而且两个序列长度相同,也可以使用最小表示法,或者kmp,或hash等其它高效的匹配算法. code: C. Dasha and Pass

codeforces 的20道C题

A - Warrior and Archer CodeForces - 595C n  偶数  然后n个数字 A B 轮流取一个 A让差变小B让差变大 直到最后2 个   求的是最小剩下的差 最后剩下的 L R  相距 n/2    求一下最小的就行 #include <iostream> #include <cstdio> #include <cmath> #include <map> #include <algorithm> #include

CodeForces - 626D

CodeForces - 626D 前缀和+概率cnt[i]表示差为i的数对的数量;sum[]为cnt的前缀和i表示第一回合的差,j表示第二回合的差,i+j小于第3回合,第三回合一共sum[5000]-sun[i+j],最后用组合公式算一下 #include <iostream> #include <cstdio> #include <queue> #include <algorithm> #include <cmath> #include &l

【集训第五天&#183;考试+数位】考试真心用不上算法~~~~~~~~~

早上,考了一堂试,noip2011D2的题,只得了150 .... T1是一道水题,自己在草稿纸上画画就能推出来,要用到杨辉三角. T2有点扯淡.原题http://www.codevs.cn/problem/1138/ 我看数据非常大,本以为是高级数据结构,但自己不会写于是跑了个二分+暴力,想行到竟然50分,他们写的高级数据结构没分. 正解是 二分+前缀优化暴力  .在每次check时先跑一遍所有矿物求出前缀,再循环每个区间,用 (r)-(l-1) 即可. T3是一道贪心题,非常好的贪心题目.原

CF713C Sonya and Problem Wihtout a Legend (经典dp)

一个经典的通过增长减小大小来求使得序列单调性的最小代价. 对于这道题,有一个前置题是不要求要严格单调,而是不严格单调 这样的话,我们可以得到一个性质,最后所有的值都是在原序列当中的,这其实用贪心的想法想一想就好,因为一旦通过加减与左边或右边相等,就没必要再加减了 但是本题要求严格,这就很难说了,因此要考虑将一个问题转化成已知的问题 对于原先的问题,其实就是a[i]-a[j]>=0就好 那么现在的问题是a[i]-a[j]>=i-j,因此我们只要对输入的原数列减下标i,就转化成上面的问题了 也就是