Problem C
题面
You are given an array a1,a2,…,an consisting of integers from 0 to 9. A subarray al,al+1,al+2,…,ar−1,ar is good if the sum of elements of this subarray is equal to the length of this subarray (∑i=lrai=r−l+1).
For example, if a=[1,2,0], then there are 3 good subarrays: a1…1=[1],a2…3=[2,0] and a1…3=[1,2,0].
Calculate the number of good subarrays of the array a.
Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.
The first line of each test case contains one integer n (1≤n≤105) — the length of the array a.
The second line of each test case contains a string consisting of n decimal digits, where the i-th digit is equal to the value of ai.
It is guaranteed that the sum of n over all test cases does not exceed 105.
Output
For each test case print one integer — the number of good subarrays of the array a.
思路
让我们找有多少个子串,使得这串长度等于所有元素之和。我刚开始想到的n2的dp,显然被卡。所以我们考虑线性做法,由于题目涉及连续区间和,我们首先想到的就是前缀和,那么我们考虑一下怎么搞,使得牛逼串最多。如果一个串全都是1,那么显然所以的串都成立。所以我们只需要在累加前缀和的时候减去一个1,这样的话,如果有相等的数字出现,就代表有多少个牛逼串。如果牛逼串不以1开头,那么正确性也很显然,因为中间一段是0,所以只要有相等,那么依旧是有牛逼串的出现。
代码实现
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
int t;
string s;
int main () {
// freopen ("data.in","r",stdin);
cin>>t;
while (t--) {
int n;
cin>>n;
cin>>s;
vector <int > p(n+1);
rev (i,0,n) {
p[i+1]=p[i]+s[i]-'1';
}
map <int,int > cnt;
ll ans=0;
rep (i,0,n) {
ans+= cnt[p[i]]++;
}
cout<<ans<<endl;
}
// fclose (stdin);
return 0;
}
Problem D
题面
You are given three multisets of pairs of colored sticks:
R pairs of red sticks, the first pair has length r1, the second pair has length r2, …, the R-th pair has length rR;
G pairs of green sticks, the first pair has length g1, the second pair has length g2, …, the G-th pair has length gG;
B pairs of blue sticks, the first pair has length b1, the second pair has length b2, …, the B-th pair has length bB;
You are constructing rectangles from these pairs of sticks with the following process:
take a pair of sticks of one color;
take a pair of sticks of another color different from the first one;
add the area of the resulting rectangle to the total area.
Thus, you get such rectangles that their opposite sides are the same color and their adjacent sides are not the same color.
Each pair of sticks can be used at most once, some pairs can be left unused. You are not allowed to split a pair into independent sticks.
What is the maximum area you can achieve?
Input
The first line contains three integers R, G, B (1≤R,G,B≤200) — the number of pairs of red sticks, the number of pairs of green sticks and the number of pairs of blue sticks.
The second line contains R integers r1,r2,…,rR (1≤ri≤2000) — the lengths of sticks in each pair of red sticks.
The third line contains G integers g1,g2,…,gG (1≤gi≤2000) — the lengths of sticks in each pair of green sticks.
The fourth line contains B integers b1,b2,…,bB (1≤bi≤2000) — the lengths of sticks in each pair of blue sticks.
Output
Print the maximum possible total area of the constructed rectangles.
思路
直接的贪心有点难搞,我们考虑一下dp。排完序后进行dp就好了。
代码实现 (贴一个jangly dalao的代码)
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
inline int read() {
char ch=getchar(); int x=0, f=1;
while(ch<'0'||ch>'9') {
if(ch=='-') f = -1;
ch=getchar();
}
while('0'<=ch&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
} return x*f;
}
void chk(int &a, int b) {
a = std::max(a, b);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int nR, nG, nB;
std::cin >> nR >> nG >> nB;
std::vector<int> r(nR), g(nG), b(nB);
for (int i = 0; i < nR; ++i)
std::cin >> r[i];
for (int i = 0; i < nG; ++i)
std::cin >> g[i];
for (int i = 0; i < nB; ++i)
std::cin >> b[i];
std::sort(r.begin(), r.end());
std::sort(g.begin(), g.end());
std::sort(b.begin(), b.end());
int dp[201][201][201] = {};
for (int i = 0; i <= nR; ++i) {
for (int j = 0; j <= nG; ++j) {
for (int k = 0; k <= nB; ++k) {
if (i < nR)
chk(dp[i + 1][j][k], dp[i][j][k]);
if (j < nG)
chk(dp[i][j + 1][k], dp[i][j][k]);
if (k < nB)
chk(dp[i][j][k + 1], dp[i][j][k]);
if (i < nR && j < nG)
chk(dp[i + 1][j + 1][k], dp[i][j][k] + r[i] * g[j]);
if (i < nR && k < nB)
chk(dp[i + 1][j][k + 1], dp[i][j][k] + r[i] * b[k]);
if (j < nG && k < nB)
chk(dp[i][j + 1][k + 1], dp[i][j][k] + g[j] * b[k]);
}
}
}
std::cout << dp[nR][nG][nB] << "
";
return 0;
}