文章目录
1.前言
刚刚接触编程不久,学习到了线段树,就做一个自己的总结。可能很烂。。。
1.1什么是树?
1.1.1树的定义
树(Tree)是n(n>=0)个结点的有限集。n=0时称为空树。在任意一颗非空树中:
1.有且仅有一个特定的称为根(root)的结点;
2.当n>1时,其余结点可分为m(m>0)个互补交互的有限集T1、T2…Tm,其中每一个集合本身又是一棵树,并称为根的子树(SubTree)。
1.1.2树的特点
- n>0时,根节点是唯一的,不可能存在多个根节点。数据结构中的树只有一个根节点。
- m>0时,子树的个数没有限制,但他们一定是互不相交的。
1.1.3结点的分类
- 结点:树的结点包含一个数据元素和若干指向其子树的分支
- 结点的度(Degree):结点拥有的子树。
- 叶子结点(Leaf)/终端结点:度为0的结点。
- 分支结点/非终端结点:度不为0的结点。
- 内部结点:除根结点以外,分支结点也称为内部结点。
- 树的度:树内各结点的度的最大值。
1.2线段树算法简介
线段树,顾名思义就是由一个一个线段组成的一棵树,每个结点都是一个线段(叶子结点是单元结点),那么每个结点应该包括:
7. 区间左右端点。
8. 区间要维护的信息(情况不同,操作不同)。
即每个结点还是一个结构体。区间上可以进行区间查询,修改,求和等操作。线段树还是一棵二叉搜索树。其主要作用是高效解决连续区间的动态查询问题。
示意图:
其中结点的数字代表第几个结点,红色数字代表这个点表示的区间范围。
有结构图可知:
- 每个结点的左儿子区间的范围为[l,mid],右儿子为[mid+1,r]
- 对于结点k,左儿子结点为2k,右儿子为2k+1。
2.线段数的构造及操作实现
2.1线段树的建立
首先建立一个结构体,为了方便使用了结构体封装函数。
struct SegmentTree
{
#define lson (node << 1) //lson代表左儿子结点
#define rson (node << 1 | 1) //rson代表右儿子结点
static const int N=1e6+10;
ll sum[N << 2]; //由于线段树的特点所以数组长度开为4倍
void pushup(int node)
{
sum[node]=sum[lson]+sum[rson];
}
void build(int node, int l, int r)
{
if(l == r){
sum[node]=a[l];//注意一定是左区间
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);//从叶子结点开始不断地求和到根节点
}
}tree;
2.2单点修改
还是在同一个结构体内写。
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
sum[node]+=x;
return ;
}
int mid=l+r>>1;
//下面两步就是在二分查询。
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);//单点修改结束后,需要更新所在区间。
}
2.3区间查询
ll query(int node, int l, int r, int L, int R)
{
if(l==L&&r==R)
{
return sum[node];
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) return query(lson, l, mid, L, R);
else if(L>mid) return query(rson, mid+1,r,L,R);
else{
ll ans=0;
ans+=query(lson,l,mid,L,mid);
ans+=query(rson,mid+1,r,mid+1,R);
return ans;
}
}
2.4区间修改
void spread(int node, int l, int r)
{
if(lazylag[node])
{
int mid=l+r>>1;
sum[lson]+=1ll*lazylag[node]*(mid-l+1);
sum[rson]+=1ll*lazylag[node]*(r-mid);
lazylag[lson]+=lazylag[node];
lazylag[rson]+=lazylag[node];
lazylag[node]=0;
}
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l==L&&r==R)
{
lazylag[node]+=x;
sum[node]+=1ll*x*(r-l+1);
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) intervalchange(lson,l,mid,L,R,x);
else if(L>mid) intervalchange(rson,mid+1,r,L,R,x);
else{
intervalchange(lson,l,mid,L,mid,x);
intervalchange(rson,mid+1,r,mid+1,R,x);
}
pushup(node);
}
2.5单点查询
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
3例题
3.1【模板】单点修改,区间查询
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[1000000+1000];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
void pushup(int node)
{
sum[node]=sum[lson]+sum[rson];
}
void build(int node, int l, int r)
{
if(l == r){
sum[node]=a[l];
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
sum[node]+=x;
return ;
}
int mid=l+r>>1;
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);
}
ll query(int node, int l, int r, int L, int R)
{
if(l==L&&r==R)
{
return sum[node];
}
int mid=l+r>>1;
if(R<=mid) return query(lson, l, mid, L, R);
else if(L>mid) return query(rson, mid+1,r,L,R);
else{
ll ans=0;
ans+=query(lson,l,mid,L,mid);
ans+=query(rson,mid+1,r,mid+1,R);
return ans;
}
}
}tree;
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
tree.build(1,1,n);
while(q--)
{
int s,l1,r1;
scanf("%d%d%d",&s,&l1,&r1);
if(s==1)
{
tree.change(1,1,n,l1,r1);
}
if(s==2)
{
ll sem=tree.query(1,1,n,l1,r1);
printf("%lld\n",sem);
}
}
return 0;
}
3.2区间修改,单点查询
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[4000000+100];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
ll lazylag[N<<2];
void pushup(int node)
{
sum[node]=sum[lson]+sum[rson];
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
int mid=l+r>>1;
sum[lson]+=1ll*lazylag[node]*(mid-l+1);
sum[rson]+=1ll*lazylag[node]*(r-mid);
lazylag[lson]+=lazylag[node];
lazylag[rson]+=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
lazylag[node]=0;
if(l == r){
sum[node]=a[l];
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
// void change(int node, int l, int r, int idx,int x)
// {
// if(l==r){
// sum[node]+=x;
// return ;
// }
// spread(node,l,r);
// int mid=l+r>>1;
// if(idx<=mid) change(lson,l,mid,idx,x);
// else change(rson,mid+1,r,idx,x);
// pushup(node);
// }
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l==L&&r==R)
{
lazylag[node]+=x;
sum[node]+=1ll*x*(r-l+1);
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) intervalchange(lson,l,mid,L,R,x);
else if(L>mid) intervalchange(rson,mid+1,r,L,R,x);
else{
intervalchange(lson,l,mid,L,mid,x);
intervalchange(rson,mid+1,r,mid+1,R,x);
}
pushup(node);
}
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
// ll query(int node, int l, int r, int L, int R)
// {
// if(l==L&&r==R)
// {
// return sum[node];
// }
// int mid=l+r>>1;
// if(R<=mid) return query(lson, l, mid, L, R);
// else if(L>mid) return query(rson, mid+1,r,L,R);
// else{
// ll ans=0;
// ans+=query(lson,l,mid,L,mid);
// ans+=query(rson,mid+1,r,mid+1,R);
// return ans;
// }
// }
}tree;
int main()
{
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
tree.build(1,1,n);
while(q--)
{
int s;
scanf("%d",&s);
if(s==1)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
tree.intervalchange(1,1,n,l,r,x);
}
if(s==2)
{
int i;
scanf("%d",&i);
printf("%lld\n",tree.idquery(1,1,n,i));
}
}
return 0;
}
3.3区间修改,区间查询
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[4000000+100];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
ll lazylag[N<<2];
void pushup(int node)
{
sum[node]=sum[lson]+sum[rson];
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
int mid=l+r>>1;
sum[lson]+=1ll*lazylag[node]*(mid-l+1);
sum[rson]+=1ll*lazylag[node]*(r-mid);
lazylag[lson]+=lazylag[node];
lazylag[rson]+=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
lazylag[node]=0;
if(l == r){
sum[node]=a[l];
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
sum[node]+=x;
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l==L&&r==R)
{
lazylag[node]+=x;
sum[node]+=1ll*x*(r-l+1);
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) intervalchange(lson,l,mid,L,R,x);
else if(L>mid) intervalchange(rson,mid+1,r,L,R,x);
else{
intervalchange(lson,l,mid,L,mid,x);
intervalchange(rson,mid+1,r,mid+1,R,x);
}
pushup(node);
}
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
ll query(int node, int l, int r, int L, int R)
{
if(l==L&&r==R)
{
return sum[node];
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) return query(lson, l, mid, L, R);
else if(L>mid) return query(rson, mid+1,r,L,R);
else{
ll ans=0;
ans+=query(lson,l,mid,L,mid);
ans+=query(rson,mid+1,r,mid+1,R);
return ans;
}
}
}tree;
int main()
{
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
tree.build(1,1,n);
while(q--)
{
int s;
scanf("%d",&s);
if(s==1)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
tree.intervalchange(1,1,n,l,r,x);
}
if(s==2)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",tree.query(1,1,n,l,r));
}
}
return 0;
}
3.4派兵布阵
题目链接
题目做法:单点修改,区间求和
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[4000000+100];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
ll lazylag[N<<2];
void pushup(int node)
{
sum[node]=sum[lson]+sum[rson];
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
int mid=l+r>>1;
sum[lson]+=1ll*lazylag[node]*(mid-l+1);
sum[rson]+=1ll*lazylag[node]*(r-mid);
lazylag[lson]+=lazylag[node];
lazylag[rson]+=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
lazylag[node]=0;
if(l == r){
sum[node]=a[l];
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
sum[node]+=x;
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l==L&&r==R)
{
lazylag[node]+=x;
sum[node]+=1ll*x*(r-l+1);
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) intervalchange(lson,l,mid,L,R,x);
else if(L>mid) intervalchange(rson,mid+1,r,L,R,x);
else{
intervalchange(lson,l,mid,L,mid,x);
intervalchange(rson,mid+1,r,mid+1,R,x);
}
pushup(node);
}
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
ll query(int node, int l, int r, int L, int R)
{
if(l==L&&r==R)
{
return sum[node];
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) return query(lson, l, mid, L, R);
else if(L>mid) return query(rson, mid+1,r,L,R);
else{
ll ans=0;
ans+=query(lson,l,mid,L,mid);
ans+=query(rson,mid+1,r,mid+1,R);
return ans;
}
}
}tree;
int main()
{
int n,q;
char s[100];
cin >> q;
for (int i = 1; i <= q;i++)
{
int sum = 1;
cin >> n;
for (int j = 1; j <= n;j++)
{
scanf("%d", &a[j]);
}
tree.build(1, 1, n);
while(1)
{
getchar();
scanf("%s", s);
getchar();
if (!strcmp(s, "Query"))
{
int x, y;
scanf("%d%d", &x, &y);
if (sum)
{
printf("Case %d:\n", i);
sum = 0;
}
printf("%lld\n", tree.query(1, 1, n, x, y));
}
else if(!strcmp(s,"Add"))
{
int x, y;
scanf("%d%d", &x, &y);
tree.change(1, 1, n, x, y);
}
else if(!strcmp(s,"Sub"))
{
int x, y;
scanf("%d%d", &x, &y);
y = y * -1;
tree.change(1, 1, n, x, y);
}
else
break;
}
}
return 0;
}
3.5处理学生
原题链接
题意单点修改,求区间最值
重点是对于pushup函数的修改
void pushup(int node)
{
sum[node]=max(sum[lson],sum[rson]);
}
ac代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[4000000+100];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
ll lazylag[N<<2];
void pushup(int node)
{
sum[node]=max(sum[lson],sum[rson]);
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
int mid=l+r>>1;
sum[lson]+=1ll*lazylag[node]*(mid-l+1);
sum[rson]+=1ll*lazylag[node]*(r-mid);
lazylag[lson]+=lazylag[node];
lazylag[rson]+=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
//lazylag[node]=0;
if(l == r){
sum[node]=a[l];
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
if(x>sum[node])
sum[node] = x;
return ;
}
//spread(node,l,r);
int mid=l+r>>1;
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l==L&&r==R)
{
lazylag[node]+=x;
sum[node]+=1ll*x*(r-l+1);
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) intervalchange(lson,l,mid,L,R,x);
else if(L>mid) intervalchange(rson,mid+1,r,L,R,x);
else{
intervalchange(lson,l,mid,L,mid,x);
intervalchange(rson,mid+1,r,mid+1,R,x);
}
pushup(node);
}
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
ll query(int node, int l, int r, int L, int R)
{
if(l==L&&r==R)
{
return sum[node];
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) return query(lson, l, mid, L, R);
else if(L>mid) return query(rson, mid+1,r,L,R);
else{
return max(query(lson,l,mid,L,mid),query(rson,mid+1,r,mid+1,R));
}
}
}tree;
int main()
{
int n, q;
while(scanf("%d%d", &n, &q)!=EOF)
{
for (int i = 1; i <= n;i++)
scanf("%d", &a[i]);
tree.build(1, 1, n);
while(q--)
{
char s;
scanf(" %c ", &s);
if(s=='Q')
{
int x, y;
scanf("%d%d", &x, &y);
printf("%lld\n" ,tree.query(1, 1, n, x, y));
}
else if(s=='U')
{
int x, y;
scanf("%d%d", &x, &y);
tree.change(1, 1, n, x, y);
}
}
}
return 0;
}
3.6Minimum Inversion Number
原题链接
题意
每一次将序列的首项放到最后一位
最后输出这个过程中逆序列最小是多少
题解
1:逆序数:i<j,ai>aj,如:4 5 3 2 1,
4的逆序数个数0
5的逆序数个数0
3的逆序数4 5,个数2
2的你叙述4 5 3,个数3
1的逆序数4 5 3 2,个数4
2:离散化的方法
每加入一个数,该位置对应的sum标记1,并更新。
在该位置之后的到n的范围内的1的个数就是这个数的逆序数。
如加入4,逆序数0
加入5,逆序数0
加入3,位置4,5均有1,逆序数为2
加入2,位置3,4,5均有1,逆序数为3
加入1,位置2 3 4 5,逆序数为4.
3最小逆序数对
先求出第一个序列的逆序数,然后用很巧妙的办法求下一个序列的逆序数,直到全部求出;
序列 4 5 2 1 3 6 ,此序列的逆序数为7,它等到的下一个序列为 5 2 1 3 6 4
看这个新序列的产生过程,首部删除4,尾部添加4
删除4,必然会使得这个序列的逆序数减少(4-1)个,因为4前面必定有4-1个数小于4
添加4,必然会使得这个序列的逆序数增加(6-4)个,因为4后面必定有6-4个数大于4
由此推出公式,假设移动的数为m,序列的逆序数=上一序列逆序数-(m-1)+(N-m)
因为不太会证明,只能找大佬的来了,原文链接在下面
————————————————
版权声明:本文为CSDN博主「linjiaqingggg」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接
最后附上ac代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[4000000+100];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
ll lazylag[N<<2];
void pushup(int node)
{
sum[node]=sum[lson]+sum[rson];
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
int mid=l+r>>1;
sum[lson]+=1ll*lazylag[node]*(mid-l+1);
sum[rson]+=1ll*lazylag[node]*(r-mid);
lazylag[lson]+=lazylag[node];
lazylag[rson]+=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
//lazylag[node]=0;
//if(l == r){
// sum[node]=a[l];
// return ;
//}
sum[node] = 0;
if(l==r)
return;
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
//pushup(node);
}
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
sum[node]+=x;
return ;
}
//spread(node,l,r);
int mid=l+r>>1;
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l==L&&r==R)
{
lazylag[node]+=x;
sum[node]+=1ll*x*(r-l+1);
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(R<=mid) intervalchange(lson,l,mid,L,R,x);
else if(L>mid) intervalchange(rson,mid+1,r,L,R,x);
else{
intervalchange(lson,l,mid,L,mid,x);
intervalchange(rson,mid+1,r,mid+1,R,x);
}
pushup(node);
}
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
ll query(int node, int l, int r, int L, int R)
{
//if(l==L&&r==R)
//
// return sum[node];
//}
//spread(node,l,r);
if(L<=l&&R>=r)
{
return sum[node];
}
int mid = (l + r) / 2;
//if(R<=mid) return query(lson, l, mid, L, R);
//else if(L>mid)
// return query(rson, mid + 1, r, L, R);
//else{
ll ans=0;
if(L<=mid)
ans += query(lson, l, mid, L,R);
if(R>mid)
ans += query(rson, mid + 1, r, L, R);
return ans;
//}
}
}tree;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
tree.build(1, 0, n - 1);
ll sum = 0;
for (int i = 0; i < n;i++)
{
scanf("%d", &a[i]);
sum += tree.query(1, 0, n - 1, a[i], n - 1);
tree.change(1, 0, n - 1, a[i], 1);
}
ll minx = sum;
for (int i = 0; i < n;i++)
{
sum += n - 1 - a[i] - a[i];
minx = min(minx, sum);
}
cout << minx << endl;
}
return 0;
}
3.7Color Count
原题链接
题目大意分两种操作:
1.单点修改:改变点的颜色种类
2.区间查询:输出区间内不重复的颜色个数
做法:因为题目要求的颜色不超过30所以我们可以使用二进制的特点去做。
比如[1,1]存的种类是1就存为1(2进制)种类为2就存为10(2进制)种类为3就存为100(2进制)…对于[1,2]区间就对于[1,1]及[2,2]内的值异或得到的就是[1,2]内的值。询问时对于区间内的值按位&1。如果为真计数器加1。
操作实现
void pushup(int node)
{
sum[node]=sum[lson]|sum[rson];
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
sum[lson]=lazylag[node];
sum[rson]=lazylag[node];
lazylag[lson]=lazylag[node];
lazylag[rson]=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
if(l == r){
sum[node]=2;
lazylag[node]=0;
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l>=L&&r<=R)
{
sum[node] = 1 << x;
lazylag[node] = 1 << x;
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if (L <= mid)
intervalchange(lson, l, mid, L, R, x);
if (R > mid)
intervalchange(rson, mid + 1, r, L, R, x);
pushup(node);
}
ll query(int node, int l, int r, int L, int R)
{
if(l>=L&&r<=R)
{
return sum[node];
}
spread(node,l,r);
int mid=l+r>>1;
int ans = 0;
if(R>mid)
ans |= query(rson, mid + 1, r, L, R);
if(L<=mid)
ans |= query(lson, l, mid, L, R);
return ans;
}
按位&1输出
if(s=='P')
{
int l, r;
scanf("%d%d", &l, &r);
if(l>r)
swap(l, r);
ll sw = tree.query(1, 1, q, l, r);
int ans = 0;
while(sw)
{
if(sw&1)
ans++;
sw >>= 1;
}
printf("%d\n", ans);
}
ac代码
#include<iostream>
#include<sstream>
#include<iterator>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<vector>
#include<bitset>
#include<climits>
#include<queue>
#include<iomanip>
#include<cmath>
#include<stack>
#include<map>
#include<ctime>
#include<new>
#define ll long long
using namespace std;
int a[4000000+100];
struct SegmentTree
{
#define lson (node << 1)
#define rson (node << 1 | 1)
static const int N=1e6+10;
ll sum[N << 2];
ll lazylag[N<<2];
void pushup(int node)
{
sum[node]=sum[lson]|sum[rson];
}
void spread(int node, int l, int r)
{
if(lazylag[node])
{
sum[lson]=lazylag[node];
sum[rson]=lazylag[node];
lazylag[lson]=lazylag[node];
lazylag[rson]=lazylag[node];
lazylag[node]=0;
}
}
void build(int node, int l, int r)
{
if(l == r){
sum[node]=2;
lazylag[node]=0;
return ;
}
int mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(node);
}
void change(int node, int l, int r, int idx,int x)
{
if(l==r){
sum[node]+=x;
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if(idx<=mid) change(lson,l,mid,idx,x);
else change(rson,mid+1,r,idx,x);
pushup(node);
}
void intervalchange(int node, int l, int r, int L,int R,int x)
{
if(l>=L&&r<=R)
{
sum[node] = 1 << x;
lazylag[node] = 1 << x;
return ;
}
spread(node,l,r);
int mid=l+r>>1;
if (L <= mid)
intervalchange(lson, l, mid, L, R, x);
if (R > mid)
intervalchange(rson, mid + 1, r, L, R, x);
pushup(node);
}
ll idquery(int node,int l,int r, int idx)
{
if(l==r)
{
return sum[node];
}
int mid=l+r>>1;
spread(node,l,r);
if(mid>=idx)
return idquery(lson,l,mid,idx);
else
return idquery(rson,mid+1,r,idx);
}
ll query(int node, int l, int r, int L, int R)
{
if(l>=L&&r<=R)
{
return sum[node];
}
spread(node,l,r);
int mid=l+r>>1;
int ans = 0;
if(R>mid)
ans |= query(rson, mid + 1, r, L, R);
if(L<=mid)
ans |= query(lson, l, mid, L, R);
return ans;
}
}tree;
int main()
{
int q, p, n;
while(scanf("%d%d%d",&q,&p,&n)!=EOF)
{
tree.build(1, 1, q);
while(n--)
{
char s;
scanf(" %c", &s);
if(s=='C')
{
int l, r, x;
scanf("%d%d%d", &l, &r, &x);
if(l>r)
swap(l, r);
tree.intervalchange(1, 1, q, l, r, x);
}
if(s=='P')
{
int l, r;
scanf("%d%d", &l, &r);
if(l>r)
swap(l, r);
ll sw = tree.query(1, 1, q, l, r);
int ans = 0;
while(sw)
{
if(sw&1)
ans++;
sw >>= 1;
}
printf("%d\n", ans);
}
}
}
return 0;
}
感谢观看