首页 > 其他分享 >2023河南萌新联赛第(四)场:河南大学 C.卡片翻转

2023河南萌新联赛第(四)场:河南大学 C.卡片翻转

时间:2023-08-15 14:29:02浏览次数:44  
标签:std 河南大学 int tr void rev 萌新 2023 inline

传送门

大致思路:

1. 发现一个很神奇的性质,无论是操作几的翻转,在同一行的始终在同一行,在同一列的始终在同一列。

2. 对于没有操作2的时候,我们只需要分开维护x轴和y轴哪两段区间翻转了即可,翻转用平衡树来写,这里选择的splay平衡树。

3. 对于有操作2的时候我们会发下进行两次操作2是会复原到原本的矩阵长宽,那么只进行一次操作2后续的操作1该如何维护,观察发现仅是行和列发生了交换,换成维护另一个信息即可。

#include <bits/stdc++.h>

const int N = 1e6 + 10;
typedef std::array<int, 3> ay;

int idx, n , m, root, rev, q;


struct node{
    int v, p;
    int rev, s[2], size;
    inline void init(int _v, int _p){// 初始化新建结点
        v = _v;
        p = _p;
        s[0] = s[1] = 0;
        size = 1;
    }
}tr[N];

inline void pushup(int u){//上传更新信息
    tr[u].size = tr[tr[u].s[0]].size + tr[tr[u].s[1]].size + 1;
}

inline void pushdown(int u){//下传更新信息
    if(tr[u].rev){
        std::swap(tr[u].s[0], tr[u].s[1]);
        tr[tr[u].s[0]].rev ^= 1;
        tr[tr[u].s[1]].rev ^= 1;
        tr[u].rev = 0;
    }
}

inline void rotate(int x){//左旋右旋函数
    int y = tr[x].p, z = tr[y].p;
    int k = tr[y].s[1] == x;//k为0代表是父节点的左节点,k为1代表室父节点的右节点
    tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;//更新x的父节点和y的子节点x应在的位置
    tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;//更新x的另一条边的父节点为y
    tr[x].s[k ^ 1] = y, tr[y].p = x;//更新x的子节点y的信息,和y的父节点为为x的信息
    pushup(y), pushup(x);
}

inline void splay(int x, int k){//将下标为x的旋转到下标为k的下面
    while(tr[x].p != k){
        int y = tr[x].p, z = tr[y].p;
        if(z != k)
            if((tr[z].s[0] == y) ^ (tr[y].s[0] == x))   rotate(x);//如果是折线先旋转x
            else rotate(y);//如果是一条直线那么先旋转y
        rotate(x);
    }
    if(!k)  root = x;
}

inline void insert(int v){
    int u = root, p = 0;
    while(u)    p = u, u = tr[u].s[v > tr[u].v];//决定v应该去u的左儿子还是右儿子
    u = ++ idx;
    if(p)  tr[p].s[v > tr[p].v] = u;//决定u应该去p的左儿子还是右儿子
    tr[u].init(v, p);
    splay(u, 0);
}

inline void go(int u, std::vector<int> &now){
    pushdown(u);
    if(tr[u].s[0]) go(tr[u].s[0], now);
    if(tr[u].v >= 1 && tr[u].v <= n)    now.push_back(tr[u].v);
    if(tr[u].s[1])  go(tr[u].s[1], now);
}

inline void go2(int u, std::vector<int> &now){
    pushdown(u);
    if(tr[u].s[0]) go2(tr[u].s[0], now);
    if(tr[u].v >= 1 && tr[u].v <= m)    now.push_back(tr[u].v);
    if(tr[u].s[1])  go2(tr[u].s[1], now);
}

/*
                 k
                / \
 tr[u<<1].size    
 如果左子树个数>=k 则去左子树里看
 如果左子树个数=k-1,则u就是中序遍历第k个点
 否则去右子树里看,k-=tr[u<<1].size-1
*/
inline int get_k(int k){
    int u = root;
    while(true){
        pushdown(u);
        if(tr[tr[u].s[0]].size >= k)    u = tr[u].s[0];
        else if(tr[tr[u].s[0]].size + 1 == k)   return u;
        else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1];
    }
    return -1;
}


inline void solve() {
	std::cin >> n >> m >> q;
	
	std::vector<std::vector<int>> g(n + 1, std::vector<int>(m + 1, 0));
	
	std::vector<ay> t;
	
	for (int i = 1; i <= n; i ++) 
		for (int j = 1; j <= m; j ++)
			std::cin >> g[i][j];
	
	root = idx = rev = 0;
	
	for (int i = 0; i <= n + 1; i ++)
		insert(i);
	
	std::vector<int> dx, dy;
	for (int i = 0; i < q; i ++) {
		int op, x, y;
		std::cin >> op;
		if (op == 1) {
			std::cin >> x >> y;
			t.push_back({op, x, y});
		} else t.push_back({0, 0, 0});
	}
	
	dx.push_back(0);
	dy.push_back(0);
	
	for (int i = 0; i < q; i ++) {
		auto &[op, x, y] = t[i];
		if (op) {
			if (rev) {
				int l = get_k(1), r = get_k(y + 2);
				splay(l, 0);
				splay(r, l);
				tr[tr[r].s[0]].rev ^= 1;
				if (y + 1 <= n) {
					l = get_k(y + 1), r = get_k(n + 2);
					splay(l, 0);
					splay(r, l);
					tr[tr[r].s[0]].rev ^= 1;
				}
			} else {
				int l = get_k(1), r = get_k(x + 2);
				splay(l, 0);
				splay(r, l);
				tr[tr[r].s[0]].rev ^= 1;
				
				if (x + 1 <= n) {
					l = get_k(x + 1), r = get_k(n + 2);
					splay(l, 0);
					splay(r, l);
					tr[tr[r].s[0]].rev ^= 1;
				}
			}
		} else {
			rev ^= 1;
		}
	}

	
	go(root, dx);
	

	root = idx = rev = 0;
	
	for (int i = 0; i <= m + 1; i ++)
		insert(i);
	
	for (int i = 0; i < q; i ++) {
		auto &[op, x, y] = t[i];
		if (op) {
			if (rev) {
				int l = get_k(1), r = get_k(x + 2);
				splay(l, 0);
				splay(r, l);
				tr[tr[r].s[0]].rev ^= 1;
				if (x + 1 <= m) {
					l = get_k(x + 1), r = get_k(m + 2);
					splay(l, 0);
					splay(r, l);
					tr[tr[r].s[0]].rev ^= 1;
				}
			} else {
				int l = get_k(1), r = get_k(y + 2);
				splay(l, 0);
				splay(r, l);
				tr[tr[r].s[0]].rev ^= 1;
				
				if (y + 1 <= m) {
					l = get_k(y + 1), r = get_k(m + 2);
					splay(l, 0);
					splay(r, l);
					tr[tr[r].s[0]].rev ^= 1;
				}
			}
		} else {
			rev ^= 1;
		}
	}

	go2(root, dy);
	
	if (!rev) {
		for (int i = 1; i <= n; i ++) {
			for (int j = 1; j <= m; j ++)
				std::cout << g[dx[i]][dy[j]] << ' ';
			std::cout << '\n';
		}
	} else {
		for (int i = 1; i <= m; i ++) {
			for (int j = 1; j <= n; j ++)
				std::cout << g[dx[j]][dy[i]] << ' ';
			std::cout << '\n';
		}
	}
}

int main(void) {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	
	int _ = 1;
	
	//std::cin >> _;
	while (_ --) solve();
	
	return 0;
}

标签:std,河南大学,int,tr,void,rev,萌新,2023,inline
From: https://www.cnblogs.com/qdhys/p/17631151.html

相关文章

  • [JOI 2023 Final] Advertisement 2 题解
    题解JOI王国有\(N\)位居民,从\(1\)到\(N\)编号。居民\(i\)(\(1\lei\leN\))居住在数轴上坐标\(X_i\)处,其影响力为\(E_i\)。同一个坐标可能住了多于一位居民。居民的影响力越高,广告效应也越高,但买书也越谨慎。Rie出版了一本关于信息学的书。为了让更多人购买这本书,她可......
  • 2023北京/上海/广州/深圳CSPM-3国标项目管理中级认证报名
    CSPM-3中级项目管理专业人员评价,是中国标准化协会(全国项目管理标准化技术委员会秘书处),面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系,建立健全人才职业能力评价和激励机制的要求,培养我国项目管理领域复合型人才。 【证书含金量】 ·竞聘优先·......
  • 2023东莞/成都/深圳产品经理NPDP认证8月19日开班
    产品经理国际资格认证NPDP是新产品开发方面的认证,集理论、方法与实践为一体的全方位的知识体系,为公司组织层级进行规划、决策、执行提供良好的方法体系支撑。  【认证机构】 产品开发与管理协会(PDMA)成立于1979年,是全球范围内产品开发与管理专业人士最杰出的倡导者,协助个人、企业......
  • ECMAScript 2023(ES14)中的所有新功能
    JavaScript在持续发展,近期ECMAScript14中发布添加了一批新功能,让我们一起来探索一下今年对JavaScript开发人员的新功能。时间的车轮又过去了一年,随之而来的是JavaScript的新官方版本:ECMAScript2023,也被称为ECMAScript14。今年的改进包括对数组的添加和对ECMAScript文件中shebang......
  • 2023下半年杭州/广州/深圳软考信息系统项目管理师报名
    信息系统项目管理师是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目之一,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职称资格考试。信息系统项目管理师,属于软考三个级别中的“高级”。 【报考要求】 不设学历与资历条......
  • YsOI2023 小记
    D2T1签。#include<cstdio>usingnamespacestd;intread(){/*...*/}typedeflonglongll;voidsolve(){ lln=read()-1,x=read(); lly=x; while(~y&1)y>>=1; for(inti=1;i<n;++i)y<<=1; if(x>y)y=x; printf("%lld\n"......
  • 2023.8.14
    今天上午把留下来的作业写完了,真的超级开心!有种解脱的感觉!!!真的太爽啦!明天就可以好好出去玩啦!正好和别人约了一起去玩!但是不开心的就是。。马上要开学了,真的很sad!所以趁着这几天再好好玩一下吧游戏里总算拿了一次第一!七夕要为人准备礼物啦,第一次有过这个节,忐忑加激动无论如......
  • 20230813 arm64 汇编学习 helloworld.s
    Programming with64-Bit ARMAssembly Language SingleBoardComputerDevelopment forRaspberryPiandMobileDevices —StephenSmith 32bitsARM64指令:////Assemblyprogramtoprint"helloworld"tostdout////x0-x2parameterstolinuxfunct......
  • 2023知网答题
    最终得分 真题如下:搜索即可 一、单选题1、片面追求研究成果发表的优先权,不负责任地发表明显不成熟的成果。这一行为属于()抢先发表拆分发表一稿多投重复发表您的答案:A 参考答案:A收藏答案解析:片面追求研究成果发表的优先权,不负责任地发表明显不成熟的成果,或......
  • 2023NepCTF-RE部分题解
    2023NepCTF-RE部分题解九龙拉棺过反调试很容易发现void__stdcallsub_401700()里面有tea的痕迹接出来发现只是前半部分#include<stdio.h>#include<stdint.h>#include"defs.h"#include<stdio.h>#include<stdio.h>#include<stdint.h>//加密函数......