zoukankan      html  css  js  c++  java
  • Codeforces 1146E Hot is Cold

    题意:
    给出一个序列,有两种操作:

    • (>;x) 将大于(x)的数全都取负
    • (<;x) 将小于(x)的数全都取负
      最后输出序列中的所有数最后的状态

    思路:
    我们先考虑对于一个数来说,它最后的状态只取决于它初始的时候是哪个数,而跟它所处的位置无关。
    我们注意到序列中的数的范围是([-10^{5}, 10^5]),那么我们只需要处理出每个数在经过(q)次操作后的状态是什么,最后查表就好了。
    我们定义一个状态(1)(-1),分别表示一个数的当前状态是取负了还是没有取负。

    我们以(>;x)这个操作为例:

    1. 如果(x > 0),那么也就是说([x + 1, 10^5])这部分的数的状态肯定是-1, 并且([-10^5, -x - 1])这部分数的状态肯定是(1),而不用管它们之前是什么状态,那么直接区间赋值就好了
    2. 如果(x < 0),那么([x + 1, -x - 1])这部分数的状态是反转,([-x, 10^5])这部分数的状态肯定是(-1)([-10^5, x])这部分数的状态肯定是(1),那么区间反转就好了
      用线段树维护区间赋值和区间反转就可以了,同理(<;x)的操作也类似处理
    #include <bits/stdc++.h>
    using namespace std;
    
    #define N 200010
    #define D 100005
    int n, q, a[N];
    
    struct SEG {
    	struct node {
    		int x, lazy[2];   
    		node () {
    			x = 1;
    			lazy[0] = 0;
    			lazy[1] = 1; 
    		}
    		void add1(int v) {
    			lazy[1] = 1;
    			lazy[0] = v;
    			x = v;
    		}
    		void add2(int v) {
    			x *= v; 
    			if (lazy[0] != 0) {
    				lazy[0] *= v;
    			} else {
    				lazy[1] *= v;
    			}
    		}
    	}t[N << 2];
    	void build(int id, int l,int r) {
    		if (l == r) {
    			t[id] = node();
    			return;
    		}
    		int mid = (l + r) >> 1;
    		build(id << 1, l, mid);
    		build(id << 1 | 1, mid + 1, r);
    	}
    	void pushdown(int id) {
    		if (t[id].lazy[1] != 1) {
    			t[id << 1].add2(t[id].lazy[1]);
    			t[id << 1 | 1].add2(t[id].lazy[1]);
    			t[id].lazy[1] = 1;
    		}
    		if (t[id].lazy[0] != 0) {
    			t[id << 1].add1(t[id].lazy[0]);
    			t[id << 1 | 1].add1(t[id].lazy[0]);
    			t[id].lazy[0] = 0;
    		}
    	}
    	void update1(int id, int l ,int r, int ql, int qr, int v) {
    		if (ql > qr) {
    			return;
    		}
    		if (l >= ql && r <= qr) {
    			t[id].add1(v);
    			return;
    		}
    		int mid = (l + r) >> 1;
    		pushdown(id);
    		if (ql <= mid) update1(id << 1, l, mid, ql, qr, v);
    		if (qr > mid) update1(id << 1 | 1, mid + 1, r, ql, qr, v);
    	}
    	void update2(int id, int l, int r, int ql, int qr, int v) {
    		if (ql > qr) {
    			return;
    		}
    		if (l >= ql && r <= qr) {
    			t[id].add2(v);
    			return;
    		}
    		int mid = (l + r) >> 1;
    		pushdown(id);
    		if (ql <= mid) update2(id << 1, l, mid, ql, qr, v);
    		if (qr > mid) update2(id << 1 | 1, mid + 1, r, ql, qr, v);
    	}
    	int query(int id, int l, int r, int pos) {
    		if (l == r) {
    			return t[id].x;
    		}
    		int mid = (l + r) >> 1;
    		pushdown(id);
    		if (pos <= mid) return query(id << 1, l, mid, pos);
    		else return query(id << 1 | 1, mid + 1, r, pos);
    	}
    }seg;
    
    int main() {
    	while (scanf("%d%d", &n, &q) != EOF) {
    		for (int i = 1; i <= n; ++i) {
    			scanf("%d", a + i);
    		}
    		seg.build(1, 1, 2 * D);
    		char op[10]; int x;
    		while (q--) {
    			scanf("%s%d", op, &x);
    			switch(op[0]) {
    				case '>' :
    					if (x < 0) {
    						seg.update2(1, 1, 2 * D, x + 1 + D, -x - 1 + D, -1);
    						seg.update1(1, 1, 2 * D, -100000 + D, x + D, 1);
    						seg.update1(1, 1, 2 * D, -x + D, 100000 + D, -1);
    					} else {
    						seg.update1(1, 1, 2 * D, x + 1 + D, 100000 + D, -1);
    						seg.update1(1, 1, 2 * D, -100000 + D, -x - 1 + D, 1);
    					}
    					break;
    				case '<' :
    					if (x > 0) {
    						seg.update2(1, 1, 2 * D, -x + 1 + D, x - 1 + D, -1);
    						seg.update1(1, 1, 2 * D, x + D, 100000 + D, 1);
    						seg.update1(1, 1, 2 * D,  -100000 + D, -x + D, -1);	
    					} else {
    						seg.update1(1, 1, 2 * D, -100000 + D, x - 1 + D, -1);
    						seg.update1(1, 1, 2 * D, -x + 1 + D, 100000 + D, 1);
    					}
    					break; 
    				default : 
    					assert(0);	
    			}
    		//	for (int i = -5; i <= 5; ++i) {
    		//		printf("%d%c", seg.query(1, 1, 2 * D, i + D), " 
    "[i == 5]);
    		//	}
    		}
    		for (int i = 1; i <= n; ++i) {
    			printf("%d%c", a[i] * seg.query(1, 1, 2 * D, a[i] + D), " 
    "[i == n]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    概率论
    英语单词每日学习
    网上学习新课程--使用开发板动手进行uboot、内核以及驱动移植
    csdn专家主页
    material of DeepLearning
    I2C协议
    SVN appears to be part of a Subversion 问题心得
    @清晰掉 各种类型32位与64位下各类型长度对比
    超级方便的linux命令手册
    HTTP协议详解(转)
  • 原文地址:https://www.cnblogs.com/Dup4/p/10746778.html
Copyright © 2011-2022 走看看