[CSP-S模擬測試]:甜圈(線段樹)

題目描述

  $D$先生,是一個了不得的甜甜圈製造商。今天,他的廚房準備在日出以前製做甜甜圈。$D$先生瞬間完成了$N$個油炸圈餅。可是,這些油炸圈餅得先通過各類裝飾任務才能夠成爲甜甜圈銷售:填充奶油,浸入巧克力,打頂可愛,豐富多彩的東西等等。
  裝飾任務有$K$個,任務編號爲$1$到$K$,而且每個甜甜圈都必須嚴格按照$K$個任務以$1,2,...,K$的順序僅完成一次,才能成爲銷售物品。
  $D$先生將$N$個甜甜圈排成一列,他彷佛打算一次完成每一個裝飾任務。可是,昨天晚上熬夜的$D$先生每一個任務只裝飾了部分連續區間的甜甜圈。這顯然是一個錯誤!不只如此,他還多是作了幾回同一任務,任務的順序也是混亂的。
  沒有通過正確流程裝飾的甜甜圈不能做爲銷售物品提供,因此他應該把它們丟掉。幸運的是,有數據依次記錄了他所作的一系列任務。數據包含如下信息:對於每一個任務,裝飾的甜甜圈的連續區間$[l,r]$和任務的$ID\ x$。
  請編寫一個程序,列舉可在展現櫃中顯示的甜甜圈的數量,做爲銷售給定記錄數據的答案。
c++


輸入格式

第一行兩個整數$N$和$K$,表示有$N$個甜甜圈和$K$個任務。
第二行一個整數$T$,表示$D$先生依次完成了$T$個區間的裝飾。
接下來$T$行,每行三個正整數$l_i,r_i,x_i$,分別表示區間$[l_i,r_i]$的甜甜圈完成了$ID$爲$x_i$的裝飾任務。
ui


輸出格式

一個整數,表示能做爲展現的甜甜圈的數量。spa


樣例

樣例輸入:blog

5 3
5
2 3 1
1 3 2
4 5 1
2 4 3
3 5 2
it

樣例輸出:class

1程序


數據範圍與提示

樣例解釋:統計

$1$號甜甜圈沒有完成任務$1$就完成了任務$2$因此拋棄,$3$號甜甜圈的任務$2$被重複完成了$2$次,拋棄!$4$號甜甜圈先完成了任務$3$再完成任務$2$,拋棄!$5$號甜甜圈沒有完成任務$3$,拋棄!因此只有$2$能夠展現。數據

數據範圍:di

對於$40\%$的數據,$N,K,T\leqslant 5,000$
對於另外$20\%$的數據,$K\leqslant 100$
對於另外$10\%$的數據,$l_i=r_i$
對於$100\%$的數據,$1\leqslant N,K,T\leqslant 200,000,x_i\leqslant K,1\leqslant l_i\leqslant r_i\leqslant N$


題解

顯然是一道線段樹,咱們考慮如何維護。

用兩個懶標記,分別表示其上端點和下端點,$-1$表示沒有懶標記,$-2$表示這段區間已經不合法便可。

最後將整棵樹跑一邊便可統計答案。

時間複雜度:$\Theta(N\log N+T\log N)$。

指望得分:$100$分。

實際得分:$100$分。


代碼時刻

#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
int N,K,T;
int tr[1000000],lz1[1000000],lz2[1000000];
int ans;
void build(int x,int l,int r)
{
	lz1[x]=lz2[x]=-2;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(L(x),l,mid);
	build(R(x),mid+1,r);
}
void pushdown(int x)
{
	if(lz1[x]==-2)return;
	if(lz1[x]==-1)
	{
		tr[L(x)]=tr[R(x)]=lz1[L(x)]=lz1[R(x)]=lz2[L(x)]=lz2[R(x)]=-1;
		return;
	}
	if(tr[L(x)]!=-1)
	{
		if(tr[L(x)]+1==lz1[x])tr[L(x)]=lz2[x];
		else tr[L(x)]=-1;
	}
	if(tr[R(x)]!=-1)
	{
		if(tr[R(x)]+1==lz1[x])tr[R(x)]=lz2[x];
		else tr[R(x)]=-1;
	}
	if(lz1[L(x)]!=-1)
	{
		if(lz1[L(x)]==-2){lz1[L(x)]=lz1[x];lz2[L(x)]=lz2[x];}
		else if(lz2[L(x)]+1==lz1[x])lz2[L(x)]=lz2[x];
		else lz1[L(x)]=lz2[L(x)]=-1;
	}
	if(lz1[R(x)]!=-1)
	{
		if(lz1[R(x)]==-2){lz1[R(x)]=lz1[x];lz2[R(x)]=lz2[x];}
		else if(lz2[R(x)]+1==lz1[x])lz2[R(x)]=lz2[x];
		else lz1[R(x)]=lz2[R(x)]=-1;
	}
	lz1[x]=lz2[x]=-2;
}
void change(int x,int l,int r,int L,int R,int w)
{
	if(r<L||R<l)return;
	if(L<=l&&r<=R)
	{
		if(tr[x]!=-1)
		{
			if(tr[x]+1==w)tr[x]++;
			else tr[x]=-1;
		}
		if(lz1[x]!=-1)
		{
			if(lz1[x]==-2)lz1[x]=lz2[x]=w;
			else if(lz2[x]+1==w)lz2[x]++;
			else lz1[x]=lz2[x]=-1;
		}
		return;
	}
	pushdown(x);
	int mid=(l+r)>>1;
	change(L(x),l,mid,L,R,w);
	change(R(x),mid+1,r,L,R,w);
}
void ask(int x,int l,int r)
{
	if(l==r)
	{
		if(tr[x]==K)ans++;
		return;
	}
	pushdown(x);
	int mid=(l+r)>>1;
	ask(L(x),l,mid);
	ask(R(x),mid+1,r);
}
int main()
{
	scanf("%d%d%d",&N,&K,&T);
	build(1,1,N);
	while(T--)
	{
		int l,r,x;
		scanf("%d%d%d",&l,&r,&x);
		change(1,1,N,l,r,x);
	}
	ask(1,1,N);
	printf("%d",ans);
	return 0;
}

rp++

相關文章
相關標籤/搜索