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,超级开心!!!
Code:
/*
* 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);
}
}
}
Code2:
#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;
int zero;//sum
int one;
}que[200005 * 4];
int n, m, x, a[200005], ql, qr;
ll pre1[200005], pre2[200005];//小于x的是pre1,大于x的是pre2
int cnt1 = 1, cnt2 = 1;
ll val;
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;
if (que[k].mark == 0)
{
que[k << 1].zero = que[k << 1].r - que[k << 1].l + 1;
que[k << 1 | 1].zero = que[k << 1 | 1].r - que[k << 1 | 1].l + 1;
que[k << 1].one = 0;
que[k << 1 | 1].one = 0;
}
else
{
que[k << 1].zero = 0;
que[k << 1 | 1].zero = 0;
que[k << 1].one = que[k << 1].r - que[k << 1].l + 1;
que[k << 1 | 1].one = que[k << 1 | 1].r - que[k << 1 | 1].l + 1;
}
que[k].mark = -1;
}
}
void build(int left = 1, int right = n, int k = 1)
{
que[k].l = left;
que[k].r = right;
que[k].mark = -1;
if (left == right)
{
if (a[left] <= x)
que[k].zero++;
else
que[k].one++;
return;
}
imid;
build(lson);
build(rson);
up(k);
}
void update(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return;
if (ql <= left && right <= qr)
{
que[k].mark = val;
if (val == 0)
{
que[k].zero = que[k].r - que[k].l + 1;
que[k].one = 0;
}
else
{
que[k].zero = 0;
que[k].one = que[k].r - que[k].l + 1;
}
return;
}
down(k);
imid;
update(lson);
update(rson);
up(k);
}
//区间ql-qr中 0 的个数
int query_zero(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k].zero;
down(k);
imid;
return query_zero(lson) + query_zero(rson);
}
//区间ql-qr中 1 的个数
int query_one(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k].one;
down(k);
imid;
return query_one(lson) + query_one(rson);
}
int main()
{
scanf("%d%d%d", &n, &m, &x);
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
if (a[i] <= x)
pre1[cnt1++] = a[i];
else
pre2[cnt2++] = a[i];
}
for (int i = 1; i < cnt1; i++)
pre1[i] += pre1[i - 1];
for (int i = 1; i < cnt2; i++)
pre2[i] += pre2[i - 1];
build();
int op, l, r;
while (m--)
{
scanf("%d%d%d", &op, &l, &r);
//pre1是0,pre2是1
if (op == 1)
{
int q0 = 0, q1 = 0, w0 = 0, w1 = 0;
if (1 <= r)
{
ql = 1;
qr = r;
q0 = query_zero();
q1 = query_one();
}
if (1 <= l - 1)
{
ql = 1;
qr = l - 1;
w0 = query_zero();
w1 = query_one();
}
printf("%lld\n", pre1[q0] - pre1[w0] + pre2[q1] - pre2[w1]);
}
else if (op == 2)
{
ql = l;
qr = r;
int zero = query_zero();
int one = query_one();
ql = l;
qr = l + zero - 1;
val = 0;
update();
ql = l + zero;
qr = r;
val = 1;
update();
}
else
{
ql = l;
qr = r;
int zero = query_zero();
int one = query_one();
ql = l;
qr = l + one - 1;
val = 1;
update();
ql = l + one;
qr = r;
val = 0;
update();
}
}
}