ZOJ - 1610 区间修改+暴力单点查询
一、内容
题意:给定【1,8000】区间,给定n组操作,每次将一段区间修改成某种颜色(对上一次颜色进行覆盖),最后问你能看到多少种颜色,且每种颜色有多少段。
二、思路
- 题目给定的区间是(x, y】左开右闭的区间
- 进行对区间的修改即可,每次记录下lazy,修改时候pushdown。
- 查询的时候采取单点查询,用last=-1,记录下上一次的颜色从1。。。。8000每个点进行查询如果与上一种颜色不相同,则这种颜色段数++。
三、代码
#include<bits/stdc++.h>
using namespace std;
#define sc(n) scanf("%c",&n)
#define sd(n) scanf("%d",&n)
#define pd(n) printf("%d\n", (n))
#define sdd(n,m) scanf("%d %d",&n,&m)
#define sddd(n,m,z) scanf("%d %d %d",&n,&m,&z)
#define pdd(n,m) printf("%d %d\n",n, m)
#define ms(a,b) memset(a,b,sizeof(a))
#define all(c) c.begin(),c.end()
#define pb push_back
#define fi first
#define se second
#define mod(x) ((x)%MOD)
#define lowbit(x) (x & (-x))
#define gcd(a,b) __gcd(a,b)
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<string> VS;
const int MOD = 1e9 + 7;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int maxn = 8e3 + 5;
int n, color[maxn << 2], vis[maxn << 2], last, x, y, c;
void pushdown(int id) {
if (color[id] == -1) return;
color[id << 1] = color[id << 1 | 1] = color[id];
color[id] = -1;
}
void update(int id, int l, int r, int x, int y, int c) {
if (x <= l && y >= r) {
color[id] = c;
return;
}
pushdown(id);
int m = (l + r) >> 1;
if (x <= m) update(id << 1, l, m, x, y, c);
if (y > m) update(id << 1 | 1, m + 1, r, x, y, c);
}
void query(int id,int l,int r) {
if (l == r) {
if (color[id] != -1 && color[id] != last) {
vis[color[id]]++;
}
//-1也要记录 没有颜色
last = color[id];
return;
}
pushdown(id);
int mid = (l + r) >> 1;
query(id << 1, l, mid);
query(id << 1 | 1, mid + 1, r);
}
int main() {
//freopen("in.txt", "r", stdin);
//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
while (sd(n) != EOF) {
ms(color, -1); ms(vis, 0);
while (n--) {
sddd(x, y, c);
update(1, 1, 8000, x + 1, y, c);
}
query(1, 1, 8000);
last = -1;
for (int i = 0; i <= 8000; i++) {
if (vis[i]) printf("%d %d\n", i, vis[i]);
}
printf("\n");
}
return 0;
}