Codeforces 665 F题
题目链接:https://codeforces.com/contest/1401/problem/F
思路:
1. 结论一:多个reverse操作,交换顺序不影响结果
2. 结论二:Swap(k) = Reverse(K+1) +Reverse(K),这个结论也不难,这样可以省略掉swap操作的实现。
3. 用线段树 + lazy标记实现,然后各种位运算(哈哈,我最喜欢位运算了)
毕业到现在,至少一年多没怎么写题了,还是蛮顺利的,就是写的慢一点
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
#define N ((1<<18)+1)
struct NODE {
NODE* l;
NODE* r;
long long sum; // 和
int need_reverse;
int num; // 有几个数值
int depth;
NODE() {
l = r = nullptr;
need_reverse = 0;
sum =0;
}
void update(){ // 更新当前树上的值
sum = l->sum + r->sum;
}
void build(int* a, int len, int d) {
num = len;
depth = d;
if (num == 1) {
sum = a[0];
return ;
}else {
l = new NODE();
r = new NODE();
int half = len>>1;
l->build(a, half, d-1);
r->build(a + half, half, d-1);
update();
}
}
void pushdown() {
// 将reverse 标记push down
if (!need_reverse || num == 1) {
return ;
} else {
if (need_reverse & (1<<depth)){
swap(l, r);
need_reverse ^= 1<<(depth - 1);
}
l->need_reverse ^= need_reverse;
r->need_reverse ^= need_reverse;
need_reverse = 0;
}
}
void replace(int pos, int val) { // 位置pos(1..2^n)改成val
pushdown();
if (pos > num || pos <1) { // 不在当前子树上
return;
}
if (num == 1){
sum = val;
return ;
}
l->replace(pos, val);
r->replace(pos - (num >>1), val);
update();
}
void reverse(int k) { // depth
need_reverse ^= (1<<k);
}
long long get_sum(int a, int b) {
pushdown();
if (b >= num) b = num;
if (a <= 1) a = 1;
if (a == 1 && b == num) // 被包含
return sum;
long long sumlr = 0;
// 左
int half = num >>1;
if (a <= half)
sumlr += l->get_sum(a, b);
if (b >half)
sumlr += r->get_sum(a - half, b- half);
return sumlr;
}
void print(){ // debug
pushdown();
if (num == 1){
std::cout<< sum << " ";
}else{
l->print();
r->print();
}
}
};
int a[N], q;
int n;
NODE *root = new NODE();
int main(){
scanf("%d%d", &n, &q);
for (int i=0;i < (1<<n); i++){
scanf("%d", a+i);
}
root->build(a, 1 << n, n);
// root->print();
// std::cout<< "debug\n";
while (q--){
int op;
scanf("%d", &op);
if (op == 1) {
int pos, val;
scanf("%d%d", &pos, &val);
root->replace(pos, val);
}else if (op == 2){
int k;
scanf("%d", &k);
root->reverse(k);
}else if (op == 3){
int k;
scanf("%d", &k);
root->reverse(k+1);
root->reverse(k);
}else if (op ==4){
int l, r;
scanf("%d%d", &l, &r);
std::cout<<root->get_sum(l, r) << std::endl;
}
// root->print();
// std::cout<< "debug\n";
}
return 0;
}
版权声明:本文为vcvycy原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。