首页 > 其他分享 >CSP2020-12-T5

CSP2020-12-T5

时间:2022-11-02 19:01:10浏览次数:61  
标签:rt std 12 return rs CSP2020 T5 tree lr

星际旅行

算法: 线段树 、离散化

题意:

你需要维护\(3\)维空间的\(n( 1 \leq n \leq 10^9)\)个点,初始时这些点的三维坐标都是\(0\)。将有以下\(4\)种操作\(m(1 \leq m \leq 4 \times 10 ^4)\)次。

  1. 给区间\([left , right]\)的所有点的三维坐标分别加上\(a , b , c\)

  2. 给区间\([left , right]\)的所有点的三维坐标分别乘上\(k\)

  3. 将区间\([left , right]\)内的点的\(x,y,z\)坐标分别变换成\(y , z , x\)

  4. 询问区间\([left , right]\)内所有点的\(x\)坐标和的平方、\(y\)坐标和的平方、\(z\)坐标和的平方和

思路:

操作\(1,2\)是线段树模板\(2\)的基本操作,正常维护即可

操作\(3\)增加一个\(tag\)用于标记是否需要进行变换,需要模\(3\)

操作\(4\)就是正常的区间查询

考虑到本题\(n\)的范围很大,所以将所有询问读入后对\(left , right + 1\)的合并集合进行排序离散化,维护的是开区间,对于单点的操作,实际表示的是左闭右开的区间,长度就是相应的\(right - left\)。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(8 * m)\)

参考代码

#include<bits/stdc++.h>
#include<unordered_map>
#define for_int(i,a,b) for(int i=(a);i<=(b);++i)
#define rep_int(i,a,b) for(int i=(a);i>=(b);--i)
#define for_ll(i,a,b) for(ll i=(a);i<=(b);++i)
#define rep_ll(i,a,b) for(ll i=(a);i>=(b);--i)
#define Ios std::ios::sync_with_stdio(false),std::cin.tie(0)
#define ull unsigned long long
#define ll long long
#define db double
#define PII std::pair<int,int>
#define PLI std::pair<long long , int>
template<class T> void chkmax(T& a, T b) { a > b ? (a = a) : (a = b); }
template<class T> void chkmin(T& a, T b) { a > b ? (a = b) : (a = a); }
template<class T> T min(T a, T b) { return a > b ? b : a; }
template<class T> T max(T a, T b) { return a < b ? b : a; }
template<class T> T abs(T a) { return a < 0 ? -a : a; }
//using namespace std;
/*
    1.注意边界情况
    2.优先考虑时间复杂度
!!! 3.求最大值时,答案应至多初始化为INT_MIN;求最小值时,答案应至少初始化为INT_MAX
    4.遇事不决先暴力
    5.代码要写简洁
    6.计数题要开long long
*/
//快速IO
template<class T>
inline bool rd(T& ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return true;
}
template<class T>
inline void print(T x) {
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
    return;
}
using std::vector;
using std::queue;
using std::string;
using std::map;
using std::unordered_map;
using std::priority_queue;
using std::cout;
using std::cin;


const int mod = 1e9 + 7;
const int N = 1e6 + 5;

struct Segment {
    int lr, rs, mid;
    long long x, y, z, tagx, tagy, tagz, tag2, tag3;
};
Segment tree[N << 2];
struct Points {
    long long x, y, z;
    Points(long long _x = 0, long long _y = 0, long long _z = 0) {
        x = _x; y = _y; z = _z;
    }
    Points operator += (const Points& a) {
        x = (x + a.x) % mod;
        y = (y + a.y) % mod;
        z = (z + a.z) % mod;
        return *this;
    }
};
int a[N], tot;
void pushUp(int rt) {
    tree[rt].x = (tree[rt << 1].x + tree[rt << 1 | 1].x) % mod;
    tree[rt].y = (tree[rt << 1].y + tree[rt << 1 | 1].y) % mod;
    tree[rt].z = (tree[rt << 1].z + tree[rt << 1 | 1].z) % mod;
}
void buildTree(int rt, int lr, int rs) {
    tree[rt].lr = lr; tree[rt].rs = rs;
    tree[rt].tag2 = 1;
    if (lr == rs) return;
    int mid = tree[rt].mid = lr + rs >> 1;
    buildTree(rt << 1, lr, mid);
    buildTree(rt << 1 | 1, mid + 1, rs);
    pushUp(rt);
    return;
}
void pushDown(int rt) {
    if (tree[rt].tag3 == 0);
    else if (tree[rt].tag3 == 1) {
        std::swap(tree[rt << 1].x, tree[rt << 1].y);
        std::swap(tree[rt << 1].y, tree[rt << 1].z);

        std::swap(tree[rt << 1].tagx, tree[rt << 1].tagy);
        std::swap(tree[rt << 1].tagy, tree[rt << 1].tagz);
        tree[rt << 1].tag3 = (tree[rt << 1].tag3 + 1) % 3;

        std::swap(tree[rt << 1 | 1].x, tree[rt << 1 | 1].y);
        std::swap(tree[rt << 1 | 1].y, tree[rt << 1 | 1].z);

        std::swap(tree[rt << 1 | 1].tagx, tree[rt << 1 | 1].tagy);
        std::swap(tree[rt << 1 | 1].tagy, tree[rt << 1 | 1].tagz);
        tree[rt << 1 | 1].tag3 = (tree[rt << 1 | 1].tag3 + 1) % 3;
        tree[rt].tag3 = 0;
    }
    else if (tree[rt].tag3 == 2) {
        std::swap(tree[rt << 1].x, tree[rt << 1].z);
        std::swap(tree[rt << 1].z, tree[rt << 1].y);
        std::swap(tree[rt << 1].tagx, tree[rt << 1].tagz);
        std::swap(tree[rt << 1].tagz, tree[rt << 1].tagy);

        tree[rt << 1].tag3 = (tree[rt << 1].tag3 + 2) % 3;

        std::swap(tree[rt << 1 | 1].x, tree[rt << 1 | 1].z);
        std::swap(tree[rt << 1 | 1].z, tree[rt << 1 | 1].y);
        std::swap(tree[rt << 1 | 1].tagx, tree[rt << 1 | 1].tagz);
        std::swap(tree[rt << 1 | 1].tagz, tree[rt << 1 | 1].tagy);
        tree[rt << 1 | 1].tag3 = (tree[rt << 1 | 1].tag3 + 2) % 3;
        tree[rt].tag3 = 0;
    }
    if (tree[rt].tag2 != 1) {
        long long tag2 = tree[rt].tag2;
        tree[rt].tag2 = 1;
        tree[rt << 1].x = tree[rt << 1].x * tag2 % mod;
        tree[rt << 1].y = tree[rt << 1].y * tag2 % mod;
        tree[rt << 1].z = tree[rt << 1].z * tag2 % mod;
        tree[rt << 1].tagx = tree[rt << 1].tagx * tag2 % mod;
        tree[rt << 1].tagy = tree[rt << 1].tagy * tag2 % mod;
        tree[rt << 1].tagz = tree[rt << 1].tagz * tag2 % mod;
        tree[rt << 1].tag2 = tree[rt << 1].tag2 * tag2 % mod;

        tree[rt << 1 | 1].x = tree[rt << 1 | 1].x * tag2 % mod;
        tree[rt << 1 | 1].y = tree[rt << 1 | 1].y * tag2 % mod;
        tree[rt << 1 | 1].z = tree[rt << 1 | 1].z * tag2 % mod;
        tree[rt << 1 | 1].tagx = tree[rt << 1 | 1].tagx * tag2 % mod;
        tree[rt << 1 | 1].tagy = tree[rt << 1 | 1].tagy * tag2 % mod;
        tree[rt << 1 | 1].tagz = tree[rt << 1 | 1].tagz * tag2 % mod;
        tree[rt << 1 | 1].tag2 = tree[rt << 1 | 1].tag2 * tag2 % mod;
    }
    int lenl = a[tree[rt << 1].rs + 1] - a[tree[rt << 1].lr];
    int lenr = a[tree[rt << 1 | 1].rs + 1] - a[tree[rt << 1 | 1].lr];
    if (tree[rt].tagx != 0) {
        long long tag = tree[rt].tagx;
        tree[rt].tagx = 0;
        tree[rt << 1].x = (tree[rt << 1].x + tag * lenl) % mod;
        tree[rt << 1].tagx = (tree[rt << 1].tagx + tag) % mod;
        tree[rt << 1 | 1].x = (tree[rt << 1 | 1].x + tag * lenr) % mod;
        tree[rt << 1 | 1].tagx = (tree[rt << 1 | 1].tagx + tag) % mod;
    }
    if (tree[rt].tagy != 0) {
        long long tag = tree[rt].tagy;
        tree[rt].tagy = 0;
        tree[rt << 1].y = (tree[rt << 1].y + tag * lenl) % mod;
        tree[rt << 1].tagy = (tree[rt << 1].tagy + tag) % mod;
        tree[rt << 1 | 1].y = (tree[rt << 1 | 1].y + tag * lenr) % mod;
        tree[rt << 1 | 1].tagy = (tree[rt << 1 | 1].tagy + tag) % mod;
    }
    if (tree[rt].tagz != 0) {
        long long tag = tree[rt].tagz;
        tree[rt].tagz = 0;
        tree[rt << 1].z = (tree[rt << 1].z + tag * lenl) % mod;
        tree[rt << 1].tagz = (tree[rt << 1].tagz + tag) % mod;
        tree[rt << 1 | 1].z = (tree[rt << 1 | 1].z + tag * lenr) % mod;
        tree[rt << 1 | 1].tagz = (tree[rt << 1 | 1].tagz + tag) % mod;
    }
    
    return;
}
Points P;
void update(int rt, int lr, int rs) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        long long len = a[tree[rt].rs + 1] - a[tree[rt].lr];
        tree[rt].x = (tree[rt].x + P.x * len) % mod;
        tree[rt].y = (tree[rt].y + P.y * len) % mod;
        tree[rt].z = (tree[rt].z + P.z * len) % mod;
        tree[rt].tagx = (tree[rt].tagx + P.x) % mod;
        tree[rt].tagy = (tree[rt].tagy + P.y) % mod;
        tree[rt].tagz = (tree[rt].tagz + P.z) % mod;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) update(rt << 1, lr, rs);
    if (tree[rt].mid < rs) update(rt << 1 | 1, lr, rs);
    pushUp(rt);
    return;
}
void update(int rt, int lr, int rs , long long val) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        tree[rt].x = tree[rt].x * val % mod;
        tree[rt].y = tree[rt].y * val % mod;
        tree[rt].z = tree[rt].z * val % mod;
        tree[rt].tagx = tree[rt].tagx * val % mod;
        tree[rt].tagy = tree[rt].tagy * val % mod;
        tree[rt].tagz = tree[rt].tagz * val % mod;
        tree[rt].tag2 = tree[rt].tag2 * val % mod;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) update(rt << 1, lr, rs , val);
    if (tree[rt].mid < rs) update(rt << 1 | 1, lr, rs , val);
    pushUp(rt);
    return;
}
void changeUpdate(int rt, int lr, int rs) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return;
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) {
        std::swap(tree[rt].x, tree[rt].y);
        std::swap(tree[rt].y, tree[rt].z);
        std::swap(tree[rt].tagx, tree[rt].tagy);
        std::swap(tree[rt].tagy, tree[rt].tagz);
        tree[rt].tag3 = (tree[rt].tag3 + 1) % 3;
        return;
    }
    pushDown(rt);
    if (tree[rt].mid >= lr) changeUpdate(rt << 1, lr, rs);
    if (tree[rt].mid < rs)  changeUpdate(rt << 1 | 1, lr, rs);
    pushUp(rt);
    return;
}
Points query(int rt, int lr, int rs) {
    if (tree[rt].lr > rs || tree[rt].rs < lr) return Points(0 , 0 , 0);
    if (tree[rt].lr >= lr && tree[rt].rs <= rs) return Points(tree[rt].x, tree[rt].y, tree[rt].z);
    Points res;
    pushDown(rt);
    if (tree[rt].mid >= lr) res += query(rt << 1, lr, rs);
    if (tree[rt].mid < rs) res += query(rt << 1 | 1, lr, rs);
    return res;
}
struct Query {
    int op, lr, rs, a, b, c, k;
};
Query q[N];
int n, m, op, lr, rs, x, y, z, k;
int getid(int val) {
    return std::lower_bound(a + 1, a + 1 + tot, val) - a;
}
int main() {
    rd(n); rd(m);
    for (int i = 1; i <= m; ++i) {
        rd(op); rd(lr); rd(rs);
        a[++tot] = lr; a[++tot] = rs + 1;
        q[i].op = op; q[i].lr = lr; q[i].rs = rs + 1;
        if (op == 1) {
            rd(x); rd(y); rd(z);
            q[i].a = x; q[i].b = y; q[i].c = z;
        }
        else if (op == 2) {
            rd(k); q[i].k = k;
        }
    }
    std::sort(a + 1, a + 1 + tot);
    tot = std::unique(a + 1, a + 1 + tot) - a - 1;
    buildTree(1, 1, tot);
    for (int i = 1; i <= m; ++i) {
        op = q[i].op; lr = getid(q[i].lr); rs = getid(q[i].rs) - 1;
        if (op == 1) {
            P = { q[i].a , q[i].b , q[i].c };
            update(1, lr, rs);
        }
        else if (op == 2) update(1, lr, rs, q[i].k);
        else if(op == 3) changeUpdate(1, lr, rs);
        else {
            Points ans = query(1, lr, rs);
            long long res = ans.x * ans.x % mod;
            res += ans.y * ans.y % mod;
            res += ans.z * ans.z % mod;
            res %= mod;
            print(res); puts("");
        }

    }
    return 0;
}

标签:rt,std,12,return,rs,CSP2020,T5,tree,lr
From: https://www.cnblogs.com/cherish-/p/16852043.html

相关文章

  • 第五章12
    【题目描述】有一只猴子,第一天摘了若干个桃子,当即吃了一半,但还觉得不过瘾,就又多吃了一个。第2天早上又将剩下的桃子吃掉一半,还是觉得不过瘾,就又多吃了两个。以后每天早......
  • SQLSERVER 2012迁移实施方案
    一、概述一台SQLSERVER2012企业版的数据库需要迁移到另一台机器上,具体情况如下:登陆账号众多,有数百个。job众多,有数百个。DB库的数量多,数据大,DB总大小达10T多,DB......
  • macOS Ventura 13系统与之前12系统不同之处的对比,你适应了没
    macOSVentura13系统升级后,发现跟macOS12Monterey的界面有很大的变化,有些设置找不到在哪里了,今天这篇文章跟大家讲讲macOSVentura13系统跟macOS12Monterey都有那些......
  • 力扣 129. 求根节点到叶节点数字之和
    129.求根节点到叶节点数字之和给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。每条从根节点到叶节点的路径都代表一个数字:例......
  • QT5.6构建打包exe方法
    打包方法项目构建为Release,将Release文件夹里的exe文件拷贝的新建文件夹out中.运行QT的MingGW,进入文件夹out执行命令:windeployqt.exeSerialport_app.exe......
  • day12 --> (Web概念回顾、Tomcat服务器、Servlet入门)
    Web相关概念的回顾: 1.软件架构:1.B/S:浏览器/服务器端2.C/S:客户端/服务器端2.资源分类:1.静态资源:所有用户访问后,得到的结果都是一样的,称之为静态资源如:html、......
  • 【原子样式实践】第12篇 一次搞定微信开发者工具的原子样式扩展
    原子样式虽好,在IDE中使用,有扩展辅助就更好。本文介绍如何开发微信开发者工具的原子样式扩展,支持原子样式的自动生成,支持特色功能组合样式,支持特色功能样式使用统计报告。1......
  • SUSE12 SP4 FOR SA*P S4安装教程(一)
    众所周知,现在SA*P S4/HANA只支持SUSE系统环境了,所以从本文开始,打算用三篇文章介绍SUSE12、HANA2.0、SA*PS41909系统的安装过程。其实安装SUSE很简单,在SUSE官网https://ww......
  • SuSE 12 SP5配置静态IP地址
    平时比较常用CentOS系统,SuSE配置静态IP与之稍有不同,在这里做一下记录设置ip地址linux-38s9:/etc/sysconfig/network#catifcfg-eth0BOOTPROTO='static'BROADCAST=......
  • CF1208D Restore Permutation
    题目传送门思路别的题解讲的比较奇妙,来一篇易懂的题解。首先我们发现最后一个位置的值是可以首先确定的,因为它前面的数已经填完了。设最后一个位置的数为\(x\),则它的......