2018 CCPC-Wannafly Winter Camp

Day5 I sorting

第一行三個整數n, q, x ( 1\leq n, q \leq 2*10^5, 0\leq x\leq 10^9)n,q,x(1≤n,q≤2∗105,0≤x≤109)表示元素的個數和詢問的個數。

接下來一行nn個整數a_1, a_2, \dots, a_n(1\leq a_i\leq 10^9)a1​,a2​,…,an​(1≤ai​≤109)。

接下來qq行,每行三個正整數p, l, r (1\leq p\leq 3), 1\leq l\leq r\leq np,l,r(1≤p≤3),1≤l≤r≤n表示操作種類和區間。

對於每個第一種操作,輸出一行,表示答案。

賽後補題一發AC,超級開心!!!

 

/*
 * 2019年1月25日
 * 題意 : 要求⽀持區間操作和區間求和
 * 
 * 容易發現<=x的數字和>x的數字的相對順序不會變。
 * 把<=x的數字當成0,>x的數字當成1。
 * 操作就是區間求和和區間賦值。
 * 區間求和就相當於搞出這是第⼏個0到第⼏個0,第⼏個1到第⼏個1,然後前綴和即可。
 * 區間賦值就相當於將前幾個值變爲0/1,將後面幾個值變爲1/0
 * 
 * 各函數作用
 * update : 區間賦值
 * shunxu :  前面出現了多少次0/1
 * query  : 當前區間內有多少個0/1
 * 
 * 各數組
 * temp1  :  <=x的數的前綴和
 * temp2  :  >x的數的前綴和
 */
#include <bits/stdc++.h>
#define ll long long
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
#define imid int mid=(left+right)/2;
using namespace std;
struct node
{
	int l;
	int r;
	ll mark;//set
	int zero;
	int one;
}que[200005 * 4];
ll val, a[200005], temp1[200005], temp2[200005], x;
int ql, qr, pre_0, pre_1, cnt_0, cnt_1, n, q;
void up(int k)
{
	que[k].zero = que[k << 1].zero + que[k << 1 | 1].zero;
	que[k].one = que[k << 1].one + que[k << 1 | 1].one;
}
void down(int k)
{
	if (que[k].mark != -1)
	{
		que[k << 1].mark = que[k].mark;
		que[k << 1 | 1].mark = que[k].mark;

		que[k << 1].one = (que[k << 1].r - que[k << 1].l + 1) * que[k].mark;
		que[k << 1].zero = (que[k << 1].r - que[k << 1].l + 1) * (1 - que[k].mark);
		que[k << 1 | 1].one = (que[k << 1 | 1].r - que[k << 1 | 1].l + 1) * que[k].mark;
		que[k << 1 | 1].zero = (que[k << 1 | 1].r - que[k << 1 | 1].l + 1) * (1 - que[k].mark);

		que[k].mark = -1;
	}
}
void build(int left, int right, int k)
{
	que[k].l = left;
	que[k].r = right;
	que[k].mark = -1;
	if (left == right)
	{
		if (a[left] == 0)
		{
			que[k].zero = 1;
			que[k].one = 0;
		}
		else
		{
			que[k].one = 1;
			que[k].zero = 0;
		}
		return;
	}
	imid;
	build(lson);
	build(rson);
	up(k);
}
//區間更新
void update(int left, int right, int k)
{
	if (qr < left || right < ql)
		return;
	if (ql <= left && right <= qr)
	{
		que[k].mark = val;
		que[k].one = (que[k].r - que[k].l + 1)*val;
		que[k].zero = (que[k].r - que[k].l + 1)*(1 - val);
		return;
	}
	down(k);
	imid;
	update(lson);
	update(rson);
	up(k);
}
//區間第一個0/1出現的位置 pre_0 pre_1表示位置  
//預設值 pre_0,pre_1 置0
//調用shunxu(1, n, 1, 0, 0);後
//全局變量pre_0,pre_1就是之前0/1的次數
void shunxu(int left, int right, int k, int pre0, int pre1)
{
	if (qr < left || right < ql)
		return;
	if (ql <= left && right <= qr)
	{
		pre_0 = min(pre_0, pre0);
		pre_1 = min(pre_1, pre1);
		return;
	}
	down(k);
	imid;
	shunxu(lson, pre0, pre1);
	pre0 += que[k << 1].zero;
	pre1 += que[k << 1].one;
	shunxu(rson, pre0, pre1);
}
//區間0/1個數 cnt_0,cnt_1表示個數
//cnt_0,cnt_1 置0
//調用query(1, n, 1);後
//cnt_0,cnt_1就是區間內0/1的次數
void query(int left, int right, int k)
{
	if (qr < left || right < ql)
		return;
	if (ql <= left && right <= qr)
	{
		cnt_0 += que[k].zero;
		cnt_1 += que[k].one;
		return;
	}
	down(k);
	imid;
	query(lson);
	query(rson);
}
int main()
{
	int op, x1 = 1, x2 = 1, qls, qrs;
	scanf("%d%d%lld", &n, &q, &x);
	for (int i = 1; i <= n; i++)
	{
		scanf("%lld", &a[i]);
		if (a[i] <= x)
		{
			temp1[x1] = a[i];
			temp1[x1] += temp1[x1 - 1];
			x1++;
			a[i] = 0;
		}
		else
		{
			temp2[x2] = a[i];
			temp2[x2] += temp2[x2 - 1];
			x2++;
			a[i] = 1;
		}
	}
	build(1, n, 1);
	while (q--)
	{
		scanf("%d%d%d", &op, &qls, &qrs);

		ql = qls;
		qr = qrs;

		//第一次出現的位置
		pre_0 = 200005;
		pre_1 = 200005;
		shunxu(1, n, 1, 0, 0);
		//printf("%d %d\n", pre_0, pre_1);

		//區間內0/1的個數
		cnt_0 = 0;
		cnt_1 = 0;
		query(1, n, 1);
		//printf("%d %d\n", cnt_0, cnt_1);
		
		if (op == 1)
		{
			printf("%lld\n", temp1[pre_0 + cnt_0] - temp1[pre_0] + temp2[pre_1 + cnt_1] - temp2[pre_1]);
		}
		else if (op == 2)
		{
			ql = qls;
			qr = qls + cnt_0 - 1;
			val = 0;
			update(1, n, 1);
			ql = qls + cnt_0;
			qr = qrs;
			val = 1;
			update(1, n, 1);
		}
		else
		{
			ql = qls;
			qr = qls + cnt_1 - 1;
			val = 1;
			update(1, n, 1);
			ql = qls + cnt_1;
			qr = qrs;
			val = 0;
			update(1, n, 1);
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章