前缀和Substring

前缀和与Substring的爱恨情仇

前缀和妙用-经典套路

Command Sequence HDU - 7108
题意,给一个只含UDRL的长度为n<1e5的串,问有多少子串的U个数==D个数,R个数==L个数,(个数可以为0).
又是一道子串的题目,前缀和就是为子串量身定制的吧。
前缀和妙用,真的太妙了。感觉这道题可以延伸一下,但是现在在寝室,有人打游戏太吵了,静不下心来,延伸不了。。

在这里插入图片描述

原来map可以pair到value,牛啊,map

点击查看代码
  
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>
#include<map>
#pragma comment(linker, "/STACK:102400000,102400000")//解决递归函数多次调用栈溢出问题
using namespace std;
#define Debug(x) cout<<#x<<':'<<x<<endl
#define INF 0x7fffffff//10^9级别,不到2^32
typedef long long ll;
const ll maxn=1e5+11;
map<pair<ll,ll>,ll> mp;
pair<ll,ll> pir[maxn];
char ar[maxn];
ll ai[maxn],bi[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
ll t;
cin>>t;
while(t--){
ll n;
cin>>n;
mp.clear();
ai[0]=bi[0]=0; pir[0].first=ai[0],pir[0].second=bi[0];
mp[pir[0]]++;
for(ll i=1;i<=n;i++){
cin>>ar[i];
if(ar[i]=='U') ai[i]=ai[i-1]+1;
else if(ar[i]=='D') ai[i]=ai[i-1]-1;
else ai[i]=ai[i-1];
if(ar[i]=='R') bi[i]=bi[i-1]+1;
else if(ar[i]=='L') bi[i]=bi[i-1]-1;
else bi[i]=bi[i-1];
pir[i].first=ai[i],pir[i].second=bi[i];
mp[pir[i]]++;
}
ll ans=0;
for(ll i=0;i<=n;i++){
ans+=mp[pir[i]]-1;
}
cout<<ans/2<<endl;
}
return 0;
}

4⭐二维前缀和好题

Portal

题意:最少需要改多少个元素,能形成需要的形状

思路:
直接暴力n^4方会超时。如果是确定矩形形状,再枚举矩形位置的情况话,不好剪枝。
相反,如果是确定了位置和矩形的行数,再枚举矩形的列数的话,就可以剪枝。
当枚举最后一列之前,判断是否大于16,大于就剪枝,16是最坏情况下的修改数。

踩坑:
算y前缀和的时候,y写成了, y[j][i]=y[j-1][i]+(a[j][i]==’1’);
正确的是:

1
2
3
4
5
6
7
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++){
x[i][j]=x[i][j-1]+(a[i][j]=='1');
y[i][j]=y[i-1][j]+(a[i][j]=='1');
s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+(a[i][j]=='1');
}
}