2019年07月25日23:56:32

  ​​https://www.hackerrank.com/challenges/sam-and-substrings/editorial​

       求一个数字字符串所有子串数字之和,dp[i]表示以第i个字符结尾的总和,列举所有出来可得到递推公式。

 

 

2018-05-08 16:56:08

​https://csacademy.com/contest/archive/task/swap_pairing/statement/​

题目意思是问,给定一个数组,每个数字都精确出现了两次。每一个操作可以交换相邻的两个数字。

要求目标是相同的数字挨在一起,求最小的操作次数。

贪心的做法是最左边的数字肯定不要动,让最右边的数字靠过来。这样最优。然后就是第一次先匹配a[1], 然后再匹配a[2]......这样。

统计的时候用树状数组维护一下就好

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <assert.h>
#include <map>

using namespace std;

const int maxn = 1e5 + 20;

int c[maxn];
int lowbit(int pos) {
return pos & (-pos);
}

int ask(int pos) {
int ans = 0;
while (pos > 0) {
ans += c[pos];
pos -= lowbit(pos);
}
return ans;
}

void update(int pos, int val) {
while (pos < maxn) {
c[pos] += val;
pos += lowbit(pos);
}
}

int a[maxn];
bool need[maxn];

map<int, int> mp;

void work() {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
for (int i = n; i >= 1; --i) {
if (mp.count(a[i]) == 0) {
mp[a[i]] = i;
} else need[i] = true;
}
long long int ans = 0;
for (int i = 1; i <= n; ++i) {
if (!need[i]) continue;
ans += mp[a[i]] - i - 1;
ans -= ask(mp[a[i]]) - ask(i - 1);
update(mp[a[i]], 1);
}
cout << ans << endl;
}


int main() {
// freopen("data.txt", "r", stdin);
work();
return 0;
}

View Code

 

​A - 一棵简单的线段树​

被卡了返回vector<long long int>

又暂时学不会返回引用,惨。。cpp白学

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 2;
const long long int inf = (long long int) 1e18;
const int oo = (int) 1e9;

struct segTree {
int L, R;
long long int sum;
int mx, mi;
} seg[maxn << 2];

int root;

int build(int L, int R) {
int now = ++root;
seg[now].sum = 0;
seg[now].mx = -oo;
seg[now].mi = oo;
if (L == R) {
seg[now].sum = seg[now].mi = seg[now].mx = 0;
return now;
}
int mid = (L + R) >> 1;
seg[now].L = build(L, mid);
seg[now].R = build(mid + 1, R);

seg[now].sum = seg[seg[now].L].sum + seg[seg[now].R].sum;
seg[now].mx = max(seg[seg[now].L].mx, seg[seg[now].R].mx);
seg[now].mi = min(seg[seg[now].L].mi, seg[seg[now].R].mi);

return now;
}

void update(int pos, int val, int L, int R, int cur) {
if (L == R) {
seg[cur].mx = seg[cur].mi = seg[cur].sum = val;
return;
}
int mid = (L + R) >> 1;
if (pos <= mid) {
update(pos, val, L, mid, seg[cur].L);
} else update(pos, val, mid + 1, R, seg[cur].R);

int lson = seg[cur].L, rson = seg[cur].R;

seg[cur].mx = max(seg[lson].mx, seg[rson].mx);
seg[cur].mi = min(seg[lson].mi, seg[rson].mi);
seg[cur].sum = seg[lson].sum + seg[rson].sum;
}

vector<long long int> ask(int be, int en, int L, int R, int cur) {

// cout << "now" << endl;
// cout << L << " " << R << endl;
if (L >= be && R <= en) {
vector<long long int> vc;
vc.push_back(seg[cur].sum);
vc.push_back(seg[cur].mx);
vc.push_back(seg[cur].mi);
return vc;
}
// cout << L << " " << R << endl;
int mid = (L + R) >> 1;

vector<long long int> ans;
for (int i = 0; i < 3; ++i) ans.push_back(0);
ans[1] = -inf;
ans[2] = inf;

if (be <= mid) {
vector<long long int> res = ask(be, en, L, mid, seg[cur].L);
// cout << "left" << " " << L << " " << R << endl;
// for (int i = 0; i < 3; ++i) {
// cout << res[i] << " ";
// }
// cout << endl;
ans[0] += res[0];
ans[1] = max(ans[1], res[1]);
ans[2] = min(ans[2], res[2]);
}
if (en >= mid + 1) {
vector<long long int> res = ask(be, en, mid + 1, R, seg[cur].R);
// cout << "right" << " " << L << " " << R << endl;
// for (int i = 0; i < 3; ++i) {
// cout << res[i] << " ";
// }
// cout << endl;
// cout << "vimi" << " " << L << " " << R << endl;
// for (int i = 0; i < 3; ++i) {
// cout << ans[i] << " ";
// }
// cout << endl;
ans[0] += res[0];
ans[1] = max(ans[1], res[1]);
ans[2] = min(ans[2], res[2]);
}
return ans;
}

void work() {
int n;
scanf("%d", &n);
build(1, n);
int q;
scanf("%d", &q);
while (q--) {
int op, one, two;
scanf("%d%d%d", &op, &one, &two);
if (op == 0) {
update(one, two, 1, n, 1);
} else {
vector<long long int> vc = ask(one, two, 1, n, 1);
// cout << "test " << vc[0] << " " << vc[1] << " " << vc[2] << endl;
printf("%lld\n", vc[0] - vc[1] - vc[2]);
}
}
}

int main() {
// freopen("data.txt", "r", stdin);
work();
return 0;
}

TLE 5

改了一改就行了

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 2;
const long long int inf = (long long int) 1e18;
const int oo = (int) 1e9;

struct segTree {
int L, R;
long long int sum;
int mx, mi;
} seg[maxn << 3];

int root;

int build(int L, int R) {
int now = ++root;
if (L == R) {
seg[now].sum = seg[now].mi = seg[now].mx = 0;
return now;
}
int mid = (L + R) >> 1;
seg[now].L = build(L, mid);
seg[now].R = build(mid + 1, R);

seg[now].sum = seg[seg[now].L].sum + seg[seg[now].R].sum;
seg[now].mx = max(seg[seg[now].L].mx, seg[seg[now].R].mx);
seg[now].mi = min(seg[seg[now].L].mi, seg[seg[now].R].mi);

return now;
}

void update(int pos, int val, int L, int R, int cur) {
if (L == R) {
seg[cur].mx = seg[cur].mi = seg[cur].sum = val;
return;
}
int mid = (L + R) >> 1;
if (pos <= mid) {
update(pos, val, L, mid, seg[cur].L);
} else update(pos, val, mid + 1, R, seg[cur].R);

int lson = seg[cur].L, rson = seg[cur].R;

seg[cur].mx = max(seg[lson].mx, seg[rson].mx);
seg[cur].mi = min(seg[lson].mi, seg[rson].mi);
seg[cur].sum = seg[lson].sum + seg[rson].sum;
}

void ask(int be, int en, int L, int R, long long int &sum, int &mx, int &mi, int cur) {
if (L >= be && R <= en) {
sum += seg[cur].sum;
mx = max(seg[cur].mx, mx);
mi = min(seg[cur].mi, mi);
return;
}
int mid = (L + R) >> 1;
if (be <= mid) {
ask(be, en, L, mid, sum, mx, mi, seg[cur].L);
}
if (en >= mid + 1) {
ask(be, en, mid + 1, R, sum, mx, mi, seg[cur].R);
}
}

void work() {
int n;
scanf("%d", &n);
build(1, n);
int q;
scanf("%d", &q);
while (q--) {
int op, one, two;
scanf("%d%d%d", &op, &one, &two);
if (op == 0) {
update(one, two, 1, n, 1);
} else {
long long int sum = 0;
int mx = -oo;
int mi = oo;
ask(one, two, 1, n, sum, mx, mi, 1);
printf("%lld\n", sum - mx - mi);
}
}
}

int main() {
// freopen("data.txt", "r", stdin);
work();
return 0;
}

View Code

 

​http://codeforces.com/contest/984/problem/D​

画图,然后变成简单的区间DP

#include <bits/stdc++.h>
using namespace std;

const int maxn = 5e3 + 20;
int dp[maxn][maxn];
int f[maxn][maxn];
int a[maxn];

int dfs(int be, int en) {
if (be > en) {
assert(false);
}
if (be == en) return dp[be][en] = f[be][en] = a[be];
if (f[be][en] != -1) return f[be][en];
int left = dfs(be, en - 1);
int right = dfs(be + 1, en);

f[be][en] = left ^ right;

dp[be][en] = max(dp[be + 1][en], max(dp[be][en - 1], left ^ right));
return f[be][en];
}

void work() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
f[i][j] = dp[i][j] = -1;
}
}
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
}
int q;
scanf("%d", &q);
while (q--) {
int L, R;
scanf("%d%d", &L, &R);
// cout << L << " " << R << endl;
dfs(L, R);
printf("%d\n", dp[L][R]);
}
}

int main() {
// freopen("data.txt", "r", stdin);
work();
return 0;
}

View Code

 

韩罗塔

#include <cstdio>
#include <cstdlib>
#include <stack>

void move(int val, char from, char broow, char to) {
printf("%d from %c broow %c to %c\n", val, from, broow, to);
}
int step;
void dfs(int n, char a, char b, char c) {
if (n == 0) return;
step++;
if (n == 1) {
move(n, a, ' ', b);
return;
}
dfs(n - 1, a, c, b);
move(n, a, ' ', b);
dfs(n - 1, c, b, a);
}

void work() {
int n = 5;
dfs(n, 'A', 'B', 'C');
printf("%d\n", step);
}

int main() {
work();
return 0;
}

View Code

 

 

光明小学的小朋友们要举行一年一度的接力跑大赛了,但是小朋友们却遇到了一个难题:设计接力跑大赛的线路,你能帮助他们完成这项工作么?
光明小学可以抽象成一张有N个节点的图,每两点间都有一条道路相连。光明小学的每个班都有M个学生,所以你要为他们设计出一条恰好经过M条边的路径。
光明小学的小朋友们希望全盘考虑所有的因素,所以你需要把任意两点间经过M条边的最短路径的距离输出出来以供参考。
你需要设计这样一个函数:
res[][] Solve( N, M, map[][]);
注意:map必然是N * N的二维数组,且map[i][j] == map[j][i],map[i][i] == 0,-1e8 <= map[i][j] <= 1e8。(道路全部是无向边,无自环)2 <= N <= 100, 2 <= M <= 1e6。要求时间复杂度控制在O(N^3*log(M))。
map数组表示了一张稠密图,其中任意两个不同节点i,j间都有一条边,边的长度为map[i][j]。N表示其中的节点数。
你要返回的数组也必然是一个N * N的二维数组,表示从i出发走到j,经过M条边的最短路径
你的路径中应考虑包含重复边的情况。

/*
* @Author: vimiliu
* @Date: 2018-07-18 15:18:42
* @Last Modified by: vimiliu
* @Last Modified time: 2018-07-18 20:22:43
*/

#include <bits/stdc++.h>
using namespace std;

const int maxn = 200 + 2;

struct Matrix {
int a[maxn][maxn];
int col, row;
void init() {
for (int i = 1; i <= row; ++i) {
for (int j = 1; j <= col; ++j) {
a[i][j] = -1; // can not go
}
}
}
};

void show(struct Matrix a) {
for (int i = 1; i <= a.row; ++i) {
for (int j = 1; j <= a.col; ++j) {
cout << a.a[i][j] << " ";
}
cout << endl;
}
cout << "debug ------ " << endl;
}

struct Matrix MatrixMul(struct Matrix a, struct Matrix b) {
struct Matrix res;
res.row = a.row; //行等于第一个矩阵的行
res.col = b.col; //列等于第二个矩阵的列
for (int i = 1; i <= a.row; ++i) {
for (int j = 1; j <= a.col; ++j) {
int val = -1; // can not go
for (int k = 1; k <= b.row; ++k) {
if (a.a[i][k] == -1 || b.a[k][j] == -1) continue;
if (val == -1) val = a.a[i][k] + b.a[k][j];
else val = min(val, a.a[i][k] + b.a[k][j]);
}
res.a[i][j] = val;
}
}
return res;
}

struct Matrix MatrixQuickPow(struct Matrix a, struct Matrix b, int n) {
while (n > 0) {
if (n & 1) {
a = MatrixMul(a, b);
}
b = MatrixMul(b, b);
n >>= 1;
}
return a;
}

int e[maxn][maxn];
int n;
void inputData() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
scanf("%d", &e[i][j]);
if (e[i][j] == 0) e[i][j] = -1;
}
}
}

void work() {

struct Matrix I;
I.row = I.col = n;
I.init();
for (int i = 1; i <= n; ++i) {
I.a[i][i] = 0;
}
struct Matrix b;
b.row = b.col = n;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
b.a[i][j] = e[i][j];
}
}
// input data
///////////////////////////
int m = 2;
struct Matrix ans = MatrixQuickPow(I, b, m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
printf("%d ", ans.a[i][j]);
}
printf("\n");
}

}

int main() {
freopen("data.txt", "r", stdin);
inputData();
work();
return 0;
}

View Code