Magic-Pen4
Source : Darkgt | |||
Time limit : 2 sec | Memory limit : 64 M |
Submitted : 207, Accepted : 57
Darkgt发明了一种强大的魔法笔。当在白色线段上画线时,白色线段就会变成红色;当在红色线段上画线时,红色线段就会变成绿色,当在绿色线段上画线时,绿色线段就会变成黄色……但是颜色的种类是有限的,经过k次改变,终将变为白色。
Input
第一行一个整数T(T<20),表示有T组case,之后每组case第一行输入三个整数:N(1 ≤ N ≤ 100000),k(1 ≤ k ≤ 100)和M(1 ≤ M ≤ 10000)。N表示线段N条单位线段,标号从1开始。k表示一共有k种颜色,接下来有M行输入,表示M条线段。每行包含三个整数P,X,Y。P=0 表示从第X条单位线段到第Y条单位线段之间用魔法笔画线。P=1 表示查询从第X条单位线段到第Y条单位线段之间连续色带的个数。起始线段为白色。
Output
对于每组询问,输出一个结果
Sample Input
1 8 2 8 0 4 3 1 1 5 0 7 8 1 4 8 0 1 1 1 7 1 0 2 7 1 3 6
Sample Output
3 3 5 2
题意:对n条线段进行多次次区间操作,进行一次操作,区间内的线段的颜色+1 如果颜色==k就变为0,然后询问某区间内有多少条色带(几个连续相同颜色的段组成一个色带)
思路:用线段树维护的数据是 一个区间中最左边的颜色和最右边的颜色,以及该区间有多少个色带,还有lazy标记对该区间执行了多少次的操作 每次PushUp的时候,把左右子树的色带加起来,然后如果中间的颜色是相同的就要-1,同时把左边的颜色置为左子树的左边的颜色,右边的颜色置为右子树的右边的颜色
注意的地方:这个题目询问和操作的时候L,R可能会出现R>L的情况,如果出现了这种情况就要转换一下L,R的值
代码:
#include<iostream>
#include<string.h>
#include<cstdio>
#include<stdio.h>
#include<map>
#include<algorithm>
#include<vector>
using namespace std;
#define MAX 100000+10
#define MOD 100000000
const int inf = 0x7fffffff;
#define lson l , m , rt<<1
#define rson m+1 , r , rt<<1|1
int add[MAX<<2];
int rcol[MAX<<2];
int lcol[MAX<<2];
int sum[MAX<<2];
int n,m,k;
void PushUp(int rt)
{
if (rcol[rt<<1]==lcol[rt<<1|1])
sum[rt] = sum[rt<<1]+sum[rt<<1|1]-1;
else
sum[rt] = sum[rt<<1]+sum[rt<<1|1];
rcol[rt] = rcol[rt<<1|1];
lcol[rt] = lcol[rt<<1];
}
void PushDown(int rt)
{
if (add[rt])
{
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
rcol[rt<<1] = (rcol[rt<<1]+add[rt])%k;
lcol[rt<<1] = (lcol[rt<<1]+add[rt])%k;
rcol[rt<<1|1] = (rcol[rt<<1|1]+add[rt])%k;
lcol[rt<<1|1] = (lcol[rt<<1|1]+add[rt])%k;
add[rt] = 0;
}
}
void Update(int L,int R,int l,int r,int rt)
{
if (L<=l && r<=R)
{
++add[rt];
rcol[rt] = (rcol[rt]+1)%k;
lcol[rt] = (lcol[rt]+1)%k;
return;
}
int m = (l+r)>>1;
PushDown(rt);
if (L<=m) Update(L,R,lson);
if (R>m) Update(L,R,rson);
PushUp(rt);
}
void build(int l,int r,int rt)
{
sum[rt] = 1;
rcol[rt] = 0;
lcol[rt] = 0;
add[rt] = 0;
if (l==r) return;
int m = (l+r)>>1;
build(lson);
build(rson);
}
pair<int,int> ans;
void query(int L,int R,int l,int r,int rt)
{
if (L<=l && r<=R)
{
ans.second += sum[rt];
if (ans.first==lcol[rt])
--ans.second;
ans.first = rcol[rt];
return;
}
int m = (l+r)>>1;
PushDown(rt);
if (L<=m) query(L,R,lson);
if (R>m) query(L,R,rson);
PushUp(rt);
}
inline void swap(int& x,int& y)
{
int tem = x;
x = y;
y = tem;
}
int main()
{
int T;
cin>>T;
while (T--)
{
scanf("%d%d%d",&n,&k,&m);
build(1,n,1);
int oper,L,R;
while (m--)
{
scanf("%d%d%d",&oper,&L,&R);
if (L>R) swap(L,R);
if (oper==0)
Update(L,R,1,n,1);
else
{
ans.first = -1;
ans.second = 0;
query(L,R,1,n,1);
printf("%d\n",ans.second);
}
}
}
}