对局匹配
直接贪心
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<functional>
#include<math.h>
//#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef vector<int> VI;
typedef pair<int, int> PII;
void makedata() {
freopen("input.txt", "w", stdout);
cout << 200000 << endl;
for(int i = 0; i < 200000; i++) cout << 1000000000 << ' ';
fclose(stdout);
}
int a[110000];
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
//makedata();
std::ios::sync_with_stdio(0), cin.tie(0);
int n, k;
cin >> n >> k;
for(int i = 0; i < n; i++) cin >> a[i];
sort(a, a + n);
int ptr = 0, ans = 0;
while(ptr < n) {
if(ptr + 2 < n && a[ptr + 2] - a[ptr] <= k) {
ans++;
ptr += 3;
} else ptr++;
}
cout << ans << endl;
return 0;
}
稀疏矩阵乘积
对应关系别搞乱就行了
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<functional>
#include<math.h>
#include<set>
#include <list>
//#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef vector<int> VI;
typedef pair<int, int> PII;
int x[3000], y[3000], w[3000], b[3000][3000], c[3000][3000];
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
std::ios::sync_with_stdio(0), cin.tie(0);
int n, p, q;
int xx, yy, ww;
cin >> n >> p >> q;
for (int i = 0; i < p; i++)cin >> x[i] >> y[i] >> w[i];
memset(b, 0, sizeof(b));
for (int i = 0; i < q; i++) {
cin >> xx >> yy >> ww;
b[xx][yy] = ww;
}
memset(c, 0, sizeof(c));
for (int i = 0; i < p; i++) {
for (int j = 1; j <= n; j++) {
c[x[i]][j] += w[i] * b[y[i]][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (c[i][j] != 0) cout << i << ' ' << j << ' ' << c[i][j] << endl;
}
}
return 0;
}
树上的等差数列
首先随便以某一个节点为根把树建起来。树上的一条路径可以看成是从某一个节点出发,在树结构上上升到某一个祖先节点,再下降到一个后代节点。记录father[x]为x节点的父节点,dep[x]为前两项为a[father[x]],a[x]的等差数列沿树结构向下最多能走的深度。枚举这个最高点r,把它的子节点按权值分类,枚举所有能构成等差数列的组合a1,a[r],a2,找到权值分别为a1和a2的子节点中dep值最大的点(且这两个点不为同一个点),那么产生了一个局部的最长等差数列l(a1)+1+l(a2),选出其中最大的输出。
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<algorithm>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<functional>
#include<math.h>
#include<set>
#include <list>
//#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef vector<int> VI;
typedef pair<int, int> PII;
map<int, VI> mp[110000];
int a[110000], father[110000], dep[110000];
VI G[110000];
void build(int x, int fa) {
father[x] = fa;
for (int i = 0; i < G[x].size(); i++) {
int u = G[x][i];
if (u == fa) continue;
auto it = mp[x].find(a[u]);
if (it == mp[x].end()) mp[x][a[u]] = VI();
mp[x][a[u]].push_back(u);
build(u, x);
}
}
void calc(int x) {
if (dep[x] != 0) return;
int d = a[father[x]] - a[x];
int aa = a[x] - d;
auto it = mp[x].find(aa);
if (it == mp[x].end()) {
dep[x] = 1;
return;
}
int tmp = 1;
for (int i = 0; i < (*it).second.size(); i++) {
int u = (*it).second[i];
calc(u);
if (dep[u] + 1 > tmp) tmp = dep[u] + 1;
}
dep[x] = tmp;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
std::ios::sync_with_stdio(0), cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
build(1, 0);
memset(dep, 0, sizeof(dep));
for (int i = 2; i <= n; i++) calc(i);
int ans = 0;
for (int i = 1; i <= n; i++) {
for (auto itl = mp[i].begin(); itl != mp[i].end(); itl++) {
int lval = (*itl).first, ldep = 0, ldot = 0;
for (int j = 0; j < (*itl).second.size(); j++) {
if (dep[(*itl).second[j]] > ldep) {
ldep = dep[(*itl).second[j]];
ldot = (*itl).second[j];
}
}
int rval = 2 * a[i] - lval, rdep = 0, rdot = 0;
auto itr = mp[i].find(rval);
if (itr == mp[i].end()) {
if (ldep + 1 > ans) ans = ldep + 1;
continue;
}
for (int j = 0; j < (*itr).second.size(); j++) {
if (dep[(*itr).second[j]] > rdep && (*itr).second[j] != ldot) {
rdep = dep[(*itr).second[j]];
rdot = (*itr).second[j];
}
}
if (ldep + 1 + rdep > ans) ans = ldep + 1 + rdep;
}
}
cout << ans << endl;
return 0;
}
翻转字符串
可以用Splay树实现反转操作。首先根据整个字符串建树,对于每次操作(l,r),首先把l左边的字符旋转到根节点上,此时(l,r)位于根节点的右子树上;然后把r右边的字符旋转到根节点的右子树的树根,这样一来,就得到了只由(l,r)构成的一棵子树:根节点的右子树的左子树,对其添加一个lazy标记,最后对树进行一个前序遍历即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxLength = 100002;
class Node{
public:
Node *child[2];
char value;
int size;
bool flip;
Node(char c) :value(c), size(1), flip(false){
child[0] = child[1] = NULL;
}
int getPosition()const{
return child[0] ? child[0]->size + 1 : 1;
}
void maintain();
void pushDown();
};
void Node::maintain(){
size = 1;
if (child[0]){
size += child[0]->size;
}
if (child[1]){
size += child[1]->size;
}
}
void Node::pushDown(){
if (flip){
swap(child[0], child[1]);
for (int i = 0; i < 2; i++){
if (child[i]){
child[i]->flip ^= 1;
}
}
flip = false;
}
}
class SplayTree{
public:
Node *root;
SplayTree(char *a, int n);
void build(Node *&node, char *begin, char *end);
void rotate(Node *&node, int direction);
void splay(Node *&node, int position);
void reverse(int begin, int end);
void traverse(Node *u);
void traverse();
};
SplayTree::SplayTree(char *a, int n){
build(root, a, a + n - 1);
}
void SplayTree::build(Node *&node, char *begin, char *end){
if (begin > end){
return;
}
char *middle = begin + (end - begin >> 1);
node = new Node(*middle);
build(node->child[0], begin, middle - 1);
build(node->child[1], middle + 1, end);
node->maintain();
}
void SplayTree::rotate(Node *&node, int direction){
Node *child = node->child[direction ^ 1];
node->child[direction ^ 1] = child->child[direction];
child->child[direction] = node;
node->maintain();
child->maintain();
node = child;
}
void SplayTree::splay(Node *&node, int position){
node->pushDown();
if (node->getPosition() != position){
int d = node->getPosition() < position;
Node *node2 = node->child[d];
position -= d ? node->getPosition() : 0;
node2->pushDown();
if (node2->getPosition() != position){
int d2 = node2->getPosition() < position;
position -= d2 ? node2->getPosition() : 0;
splay(node2->child[d2], position);
if (d == d2){
rotate(node, d ^ 1);
}
else{
rotate(node->child[d], d);
}
}
rotate(node, d ^ 1);
}
}
void SplayTree::reverse(int begin, int end){
splay(root, begin);
splay(root->child[1], end - begin + 2);
root->child[1]->child[0]->flip ^= 1;
}
void SplayTree::traverse(Node *u){
if (!u){
return;
}
u->pushDown();
traverse(u->child[0]);
if (u->value){
printf("%c", u->value);
}
traverse(u->child[1]);
}
void SplayTree::traverse(){
traverse(root);
}
int main(){
char s[maxLength] = "";
while (~scanf("%s", s + 1)){
int n = strlen(s + 1);
SplayTree splay(s, n + 2);
int k;
scanf("%d", &k);
for (int i = 0; i < k; i++){
int begin, end;
scanf("%d%d", &begin, &end);
splay.reverse(begin + 1, end + 1);
}
splay.traverse();
printf("\n");
}
return 0;
}