刷题总结2/8
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了刷题总结2/8相关的知识,希望对你有一定的参考价值。
本篇小重点:异或树https://www.luogu.com.cn/problem/P2846
用异或的0和1来模拟开关操作。一个区间只有亮灯和灭灯,所以异或之后区间亮灯的数量就是异或前区间灭灯的数量。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
int a[maxn],n,m;
struct node
int val,lazy; //val记录一个区间内亮灯的数量,lazy与1异或来模拟明暗灯
sg[maxn<<2];
void pushup(int rt)
sg[rt].val=sg[rt<<1].val+sg[rt<<1|1].val;
void pushdown(int rt,int ln,int rn)
if(sg[rt].lazy)
sg[rt<<1].lazy^=1;
sg[rt<<1|1].lazy^=1;
sg[rt<<1].val=ln-sg[rt<<1].val;//异或之后区间亮灯的数量就是异或前区间灭灯的数量
sg[rt<<1|1].val=rn-sg[rt<<1|1].val;
sg[rt].lazy=0;
void update(int L,int R,int l,int r,int rt)
if(L<=l&&r<=R)
sg[rt].val=(r-l+1)-sg[rt].val;
sg[rt].lazy^=1;
return;
int m=(l+r)>>1;
pushdown(rt,m-l+1,r-m);
if(L<=m) update(L,R,l,m,rt<<1);
if(R>m) update(L,R,m+1,r,rt<<1|1);
pushup(rt);
int query(int L,int R,int l,int r,int rt)
if(L<=l&&r<=R)
return sg[rt].val;
if(L>r||R<l)
return 0;
int m=(l+r)/2;
pushdown(rt,m-l+1,r-m);
return query(L,R,l,m,rt<<1)+query(L,R,m+1,r,rt<<1|1);
signed main()
scanf("%lld%lld",&n,&m);
while(m--)
int g,x,y;scanf("%lld%lld%lld",&g,&x,&y);
if(g==0)
update(x,y,1,n,1);
else if(g==1)
cout<<query(x,y,1,n,1)<<endl;
return 0;
1.线段树2 加法和乘法的混合修改
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
int a[maxn],n,m,p;
struct node
int val,lazy,lz;
sg[maxn<<2];
void pushup(int rt)
sg[rt].val=(sg[rt<<1].val+sg[rt<<1|1].val)%p;
void build(int l,int r,int rt)
if(l==r)
sg[rt].val=a[l];return ;
sg[rt].lazy=0;
sg[rt].lz=1;
int m=(l+r)/2;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
void pushdown(int rt,int ln,int rn)
if(sg[rt].lazy||sg[rt].lz!=1)
sg[rt<<1].val=(sg[rt].lazy*ln+(sg[rt<<1].val*sg[rt].lz)%p)%p;
sg[rt<<1|1].val=(sg[rt].lazy*rn+(sg[rt<<1|1].val*sg[rt].lz)%p)%p;
sg[rt<<1].lazy=(sg[rt].lazy+(sg[rt<<1].lazy*sg[rt].lz)%p)%p;
sg[rt<<1|1].lazy=(sg[rt].lazy+(sg[rt<<1|1].lazy*sg[rt].lz)%p)%p;
sg[rt<<1].lz=(sg[rt].lz*sg[rt<<1].lz)%p;
sg[rt<<1|1].lz=(sg[rt].lz*sg[rt<<1|1].lz)%p;
sg[rt].lz=1;
sg[rt].lazy=0;
void update(int L,int R,int C,int l,int r,int rt)
if(L<=l&&r<=R)
sg[rt].val=(sg[rt].val+C*(r-l+1))%p;
sg[rt].lazy=(sg[rt].lazy+C)%p;
return;
if(R<l||L>r) return;
int m=(l+r)>>1;
pushdown(rt,m-l+1,r-m);
if(L<=m) update(L,R,C,l,m,rt<<1);
if(R>m) update(L,R,C,m+1,r,rt<<1|1);
pushup(rt);
void update1(int L,int R,int C,int l,int r,int rt)
if(R<l||L>r) return;
if(L<=l&&r<=R)
sg[rt].val=(sg[rt].val*C)%p;
sg[rt].lazy=(sg[rt].lazy*C)%p;
sg[rt].lz=(sg[rt].lz*C)%p;
return;
int m=l+r>>1;
pushdown(rt,m-l+1,r-m);
if(L<=m) update1(L,R,C,l,m,rt<<1);
if(R>m) update1(L,R,C,m+1,r,rt<<1|1);
pushup(rt);
int query(int L,int R,int l,int r,int rt)
if(L<=l&&r<=R)
return sg[rt].val;
if(L>r||R<l)
return 0;
int m=(l+r)/2;
pushdown(rt,m-l+1,r-m);
return (query(L,R,l,m,rt<<1)+query(L,R,m+1,r,rt<<1|1))%p;
signed main()
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,n,1);
while(m--)
//memset()
int g;scanf("%lld",&g);
if(g==2)
int x,y,k;scanf("%lld%lld%lld",&x,&y,&k);
update(x,y,k,1,n,1);
else if(g==1)
int x,y,k;scanf("%lld%lld%lld",&x,&y,&k);
update1(x,y,k,1,n,1);
else if(g==3)
int x,y;scanf("%lld%lld",&x,&y);
cout<<query(x,y,1,n,1)<<endl;
return 0;
2.线段出取出区间极大值
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int n,m,a[maxn];
struct node
int val;
st[maxn<<2];
void pushup(int rt)
st[rt].val=max(st[rt<<1].val,st[rt<<1|1].val);
void build(int l,int r,int rt)
if(l==r)
st[rt].val=a[l];
return;
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
void update(int L,int R,int l,int r,int rt)
if(l==r)
if(st[rt].val<R)
st[rt].val=R;
return;
int mid=(l+r)>>1;
if(L<=mid) update(L,R,l,mid,rt<<1);
else update(L,R,mid+1,r,rt<<1|1);
pushup(rt);
int query(int L,int R,int l,int r,int rt)
if(L<=l&&r<=R)
return st[rt].val;
if(L>r||R<l)
return 0;
int mid=(l+r)>>1,ans=0;
if(L<=mid)
ans=max(ans,query(L,R,l,mid,rt<<1));
if(R>mid)
ans=max(ans,query(L,R,mid+1,r,rt<<1|1));
return ans;
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
while(m--)
char c;scanf("%s",&c);int x,y;
if(c=='Q'<以上是关于刷题总结2/8的主要内容,如果未能解决你的问题,请参考以下文章