Poj2777(线段树+标记+状态压缩)
2015-07-26 19:09
246 查看
[code]题目链接> http://poj.org/problem?id=2777
题目大意:给你一个长为L的板,然后给上边的每一段涂颜色, 给出一系列操作对应更新区间或输出该区间有多少中颜色, 本题肯定能想到线段树来解决,然后根据T<30想到用状态 压缩的方法,用位运算同时也要加上lazy标记,不然很容 易超时。
注意异或^的用法 x ^ (1 << (k - 1)) = 0 表示x的第k位(从 k = 1 开始)为1否则为0。
第一次写这方面的题,写的又长又丑,搞得我 挖了一发就不想再看自己写的代码了,而且本题 要注意所给的区间A到B可能A
[code]#include <iostream> #include <sstream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <set> #include <vector> using namespace std; const int maxn = 100000 + 5; int flag; struct node { int lazy; int sum; }; node tree[maxn*4]; void build(int p, int l, int r) { if (l == r) { tree[p].sum = 1; tree[p].lazy = 1; return; } int mid = (l+r) >> 1; build(p<<1, l, mid); build(p<<1|1, mid+1, r); tree[p].sum = tree[p<<1].sum|tree[p<<1|1].sum; } void push_down(int p, int l, int r, int z) { tree[p].lazy = 0;//这行不能丢,丢了就WA了 node &ll = tree[p<<1]; node &rr = tree[p<<1|1]; if ((ll.lazy^(1<<(z-1))) != 0) { ll.lazy = 1<<(z-1); ll.sum = ll.lazy; } if ((rr.lazy^(1<<(z-1))) != 0) { rr.lazy = 1<<(z-1); rr.sum = rr.lazy; } } void change(int p, int l, int r, int x, int y, int z) { int &s = tree[p].lazy; if (l >= x && r <= y) { if ((s^(1<<(z-1))) == 0) return; else { s = 1<<(z-1); tree[p].sum = s; } return; } for (int i = 0; i < 31; i++) { if ((s ^ (1<<i)) == 0) { push_down(p, l, r, i+1); break; } } int mid = (l+r)>>1; if (x <= mid) change(p<<1, l, mid, x, y, z); if (y > mid) change(p<<1|1, mid+1, r, x, y, z); tree[p].sum = tree[p<<1].sum|tree[p<<1|1].sum; } int query(int p, int l ,int r, int x, int y) { if (l >= x && r <= y) { return tree[p].sum; } for (int i = 0; i < 31; i++) { if ((tree[p].lazy ^ (1<<i)) == 0) { push_down(p, l, r, i+1); break; } } int mid = (l+r)>>1; int ans = 0; if (x <= mid) ans = ans|query(p<<1, l, mid, x, y); if (y > mid) ans = ans|query(p<<1|1, mid+1, r, x, y); tree[p].sum = tree[p<<1].sum|tree[p<<1|1].sum; return ans; } int main() { //freopen("input.txt", "r", stdin); int L, T, op; cin >> L >> T >> op; memset(tree, 0, sizeof(tree)); build(1, 1, L);//建树 for (int i = 0; i < op; i++) { char ch; int x, y, z; scanf(" %c", &ch); if (ch == 'C') { scanf("%d%d%d", &x, &y, &z); if (x > y) swap(x, y); change(1, 1, L, x, y, z);//更新 } else { scanf("%d%d", &x, &y); if (x > y) swap(x, y); int tmp = query(1, 1, L, x, y);//询问 int ans = 0; for (int i = 0; i <= 30; i++) { if ((tmp&(1<<i)) ) ans++; } cout << ans << endl; } } return 0; }
相关文章推荐
- HDUOJ Let the Balloon Rise 1004
- [UnityShaderCookbook 读书笔记] [01] Unity Shader 基础
- Android动态加载JAR包的实现方法
- (八十八)VFL语言初步 - 实现布局
- Validate Binary Search Tree
- (八十八)VFL语言初步 - 实现布局
- js 排序 冒泡排序,选择排序,插入排序
- BestCoder 1st Anniversary ($)
- leetcode[108]:Convert Sorted Array to Binary Search Tree
- poj 1125 Stockbroker Grapevine Floyd算法求各点之间的最短路
- Python学习日志之Python数据结构初识
- linux查看jar包内文件命令
- 剑指offer——链表相关问题总结
- N皇后摆放问题
- 双重DP实例2:K次购买股票的最大收益
- Currency System in Geraldion
- HDU 1853 Cyclic Tour
- WCF配置文件
- 单列的实现的问题
- if使用注意事项