1003
http://acm.hdu.edu.cn/showproblem.php?pid=5783
Divide the Sequence
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2232 Accepted Submission(s): 628
Problem Description
Alice has a sequence A, She wants to split A into as much as possible continuous subsequences, satisfying that for each subsequence, every its prefix sum is not small than 0.
Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An.
1≤n≤1e6
−10000≤A[i]≤10000
You can assume that there is at least one solution.
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An.
1≤n≤1e6
−10000≤A[i]≤10000
You can assume that there is at least one solution.
Output
For each test case, output an integer indicates the maximum number of sequence division.
Sample Input
6 1 2 3 4 5 6 4 1 2 -3 0 5 0 0 0 0 0
Sample Output
6 2 5
题目意思是把一个序列分成尽量多的序列,使得每个序列的前缀和大于等于0。(另外,题目数据保证每个[1, i]的前缀和大于等于0,并且一定有解)
因为忽略了括号里的条件,我觉得这是个dp问题,简单题,然后就tle了,顺手记一下dp的程序:
dp[i]表示[1, i]最多能形成多少个段。那么转移方程如下:
dp[i] = Max(dp[i], dp[j - 1] + (sum[i] - sum[j - 1] >= 0));
<span style="font-size:18px;">//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define enter putchar(10)
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define repe(i,a,b) for(int i = (a); i <= (b); ++i)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfP(a) printf("%d %d\n",a.fi,a.se)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define ds(a) int a; sf(a)
#define PR(a,b) pair<a,b>
#define fi first
#define se second
#define LL long long
#define DB double
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
int n, m;
const int N = (1e+6) + 10;
int sum[N];
int dp[N];
void check() {
repe(i, 1, n) {
printf("%d ", dp[i]);
}
enter; enter;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("Out.txt", "w", stdout);
#endif
while(~sf(n)) {
mem(dp, 0);
sum[0] = 0;
repe(i, 1, n) {
sf(sum[i]);
sum[i] += sum[i - 1];
}
repe(i, 1, n) {
repe(j, i, n) {
if(sum[j] - sum[i - 1] >= 0) dp[j] = Max(dp[j], dp[i - 1] + 1);
}
}
pf(dp[n]);
}
return 0;
}</span>后来发现是tle,我想,这个dp好像没法变成一维(因为数组没法开dp[1e + 6][1e + 6]),那可不可能把二维数组用滚动数组的方式优化成一维,但是,好想也没办法(既然一维能表示状态而且能递推,为什么要弄到二维去?)
后来我们发现我们忽略了一个条件,数据中的序列的每一项的前缀和保证大于等于0,既然这样我们就可以采用贪心的方法,sum[1, i] 保证大于等于0,加入sum[j, i]大于等于0,那么[i, j]就可以被分成一段,所以从后往前扫一遍就行了。。。
<span style="font-size:18px;">//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define enter putchar(10)
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define repe(i,a,b) for(int i = (a); i <= (b); ++i)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfP(a) printf("%d %d\n",a.fi,a.se)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define ds(a) int a; sf(a)
#define PR(a,b) pair<a,b>
#define fi first
#define se second
#define LL long long
#define DB double
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
int n, m;
#define N 1000010
int a[N];
LL sum;
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("Out.txt", "w", stdout);
#endif
while(~sf(n)) {
rep(i, 0, n) sf(a[i]);
sum = 0;
int ans = 0;
for(int i = n - 1; i >= 0; i--) {
sum += a[i];
if(sum >= 0) {
ans++;
sum = 0;
}
}
pf(ans);
}
return 0;
}</span>well, 下一题。。
1011
http://acm.hdu.edu.cn/showproblem.php?pid=5791
Two
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1500 Accepted Submission(s): 414
Problem Description
Alice gets two sequences A and B. A easy problem comes. How many pair of sequence A' and sequence B' are same. For example, {1,2} and {1,2} are same. {1,2,4} and {1,4,2} are not same. A' is a subsequence
of A. B' is a subsequence of B. The subsequnce can be not continuous. For example, {1,1,2} has 7 subsequences {1},{1},{2},{1,1},{1,2},{1,2},{1,1,2}. The answer can be very large. Output the answer mod 1000000007.
Input
The input contains multiple test cases.
For each test case, the first line cantains two integers N,M(1≤N,M≤1000). The next line contains N integers. The next line followed M integers. All integers are between 1 and 1000.
For each test case, the first line cantains two integers N,M(1≤N,M≤1000). The next line contains N integers. The next line followed M integers. All integers are between 1 and 1000.
Output
For each test case, output the answer mod 1000000007.
Sample Input
3 2 1 2 3 2 1 3 2 1 2 3 1 2
Sample Output
2 3
题目意思是求两个序列最多有多少个顺序相同的子序列。。一道大水题。
这题不是我写的,待会上传代码
无疑是dp嘛,状态表示也很好想不过转移方程得想一下。
用dp[i][j]表示a[1 , i] 能和 b[1, j] 能形成的公共子序列个数,无疑dp[i][j] = 0 (i == 0 || j == 0)
初状态就有了,现在来考虑转移方程。
先考虑a[i] != b[j] 的情况:
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];(容斥原理嘛,a[i] 和 b[j - 1]能构成的子序列个数 + a[i - 1] 和 b[j] 能构成的子序列个数 - a[i - 1] 和 b[j - 1] 能构成的子序列个数(因为在算[i, j - 1] 和 [i - 1, j]的时候重复算了一次))
那么如果a[i] == b[j] 呢?
dp[i][j] 在a[i] != b[j] 的基础上 + dp[i - 1][j - 1] + 1;因为a[i] == b[j], a[1 , i - 1] 和 b[1, j - 1] 能形成的任何一个子序列再加上a[i](同时也是b[j])又能形成新的一个子序列(并且和原来不同,因为多了a[i]),所以能形成的新的个数自然是dp[i - 1][j - 1]个了, 并且 a[i] 自己也能形成一个仅有a[i]的序列, 所以再加上1,这样就得到了 dp[i][j] .
所以状态转移方程如下:
这道题也很好解了:
Total Submission(s): 938 Accepted Submission(s): 340
比赛的时候给了一种O(n ^ 2) 的解法(预处理 + 容斥原理)果不其然超时,超时代码就不贴了,就是统计第 i 个位置比比它大的并且在它后面的数的个数,比它大的在它前面的个数,同理统计比它小的在后面和前面的个数, 然后二重循环算一算加一加减一减就好了,超时!
再去做做再来说解法。。。
这题不是我写的,待会上传代码
无疑是dp嘛,状态表示也很好想不过转移方程得想一下。
用dp[i][j]表示a[1 , i] 能和 b[1, j] 能形成的公共子序列个数,无疑dp[i][j] = 0 (i == 0 || j == 0)
初状态就有了,现在来考虑转移方程。
先考虑a[i] != b[j] 的情况:
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];(容斥原理嘛,a[i] 和 b[j - 1]能构成的子序列个数 + a[i - 1] 和 b[j] 能构成的子序列个数 - a[i - 1] 和 b[j - 1] 能构成的子序列个数(因为在算[i, j - 1] 和 [i - 1, j]的时候重复算了一次))
那么如果a[i] == b[j] 呢?
dp[i][j] 在a[i] != b[j] 的基础上 + dp[i - 1][j - 1] + 1;因为a[i] == b[j], a[1 , i - 1] 和 b[1, j - 1] 能形成的任何一个子序列再加上a[i](同时也是b[j])又能形成新的一个子序列(并且和原来不同,因为多了a[i]),所以能形成的新的个数自然是dp[i - 1][j - 1]个了, 并且 a[i] 自己也能形成一个仅有a[i]的序列, 所以再加上1,这样就得到了 dp[i][j] .
所以状态转移方程如下:
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + (a[i] == b[j] ? dp[i - 1][j - 1] + 1 : 0);这道题也很好解了:
/*************************************************************************
> File Name: 1011.cpp
> Author: Triose
> Mail: Triose@163.com
> Created Time: 2016年08月03日 星期三 13时48分21秒
************************************************************************/
//#include<bits/stdc++.h>
#include<stdio.h>
#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<iterator>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<map>
#include<set>
using namespace std;
//#define ONLINE_JUDGE
#define eps 1e-8
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define enter putchar(10)
#define rep(i,a,b) for(int i = (a); i < (b); ++i)
#define repe(i,a,b) for(int i = (a); i <= (b); ++i)
#define mem(a,b) (memset((a),b,sizeof(a)))
#define sf(a) scanf("%d",&a)
#define sfI(a) scanf("%I64d",&a)
#define sfd(a,b) scanf("%d%d",&a,&b)
#define sft(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define sfs(a) scanf("%s",a)
#define pf(a) printf("%d\n",a)
#define pfd(a,b) printf("%d %d\n",a,b)
#define pfP(a) printf("%d %d\n",a.fi,a.se)
#define pfs(a) printf("%s\n",a)
#define pfI(a) printf("%I64d\n",a)
#define ds(a) int a; sf(a)
#define PR(a,b) pair<a,b>
#define fi first
#define se second
#define LL long long
#define DB double
const double PI = acos(-1.0);
const double E = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<class T> inline T Min(T a, T b) { return a < b ? a : b; }
template<class T> inline T Max(T a, T b) { return a > b ? a : b; }
int n, m;
const int MOD = (1e+9) + 7;
#define N 1010
int a[N], b[N];
LL dp[N][N];
void Init() {
mem(dp, 0);
repe(i, 1, n) sf(a[i]);
repe(j, 1, m) sf(b[j]);
}
void solve() {
repe(i, 1, n) {
repe(j, 1, m) {
dp[i][j] = (dp[i - 1][j] + dp[i][j - 1] - dp[i- 1][j - 1] + MOD) % MOD;
if(a[i] == b[j]) {
dp[i][j] = (dp[i][j] + dp[i - 1][j - 1] + 1) % MOD;
}
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
// freopen("Out.txt", "w", stdout);
#endif
while(~sfd(n, m)) {
Init();
solve();
pfI(dp[n][m]);
}
return 0;
}1012
http://acm.hdu.edu.cn/showproblem.php?pid=5792
World is Exploding
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 938 Accepted Submission(s): 340
Problem Description
Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies:
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad.
Input
The input consists of multiple test cases.
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An.
1≤n≤50000
0≤Ai≤1e9
Each test case begin with an integer n in a single line.
The next line contains n integers A1,A2⋯An.
1≤n≤50000
0≤Ai≤1e9
Output
For each test case,output a line contains an integer.
Sample Input
4 2 4 1 3 4 1 2 3 4
Sample Output
1 0
再去做做再来说解法。。。
本文解析了三道ACM竞赛题目:序列分割、两序列相同子序列数量计算及四元组计数问题,提供了详细算法思路与代码实现。
1564

被折叠的 条评论
为什么被折叠?



