[Offer收割]编程练习赛42

时间:2023-02-13 18:09:19

对局匹配

直接贪心

[Offer收割]编程练习赛42[Offer收割]编程练习赛42
#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;
}
View Code

稀疏矩阵乘积

对应关系别搞乱就行了

[Offer收割]编程练习赛42[Offer收割]编程练习赛42
#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;
}
View Code

树上的等差数列

首先随便以某一个节点为根把树建起来。树上的一条路径可以看成是从某一个节点出发,在树结构上上升到某一个祖先节点,再下降到一个后代节点。记录father[x]为x节点的父节点,dep[x]为前两项为a[father[x]],a[x]的等差数列沿树结构向下最多能走的深度。枚举这个最高点r,把它的子节点按权值分类,枚举所有能构成等差数列的组合a1,a[r],a2,找到权值分别为a1和a2的子节点中dep值最大的点(且这两个点不为同一个点),那么产生了一个局部的最长等差数列l(a1)+1+l(a2),选出其中最大的输出。

[Offer收割]编程练习赛42[Offer收割]编程练习赛42
#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;
}
View Code

翻转字符串

可以用Splay树实现反转操作。首先根据整个字符串建树,对于每次操作(l,r),首先把l左边的字符旋转到根节点上,此时(l,r)位于根节点的右子树上;然后把r右边的字符旋转到根节点的右子树的树根,这样一来,就得到了只由(l,r)构成的一棵子树:根节点的右子树的左子树,对其添加一个lazy标记,最后对树进行一个前序遍历即可。

[Offer收割]编程练习赛42[Offer收割]编程练习赛42
#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;
}
View Code