1275. 最大数【单点修改 区间最大】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
struct node{
int l,r,v;}tr[N*4];
int m,p;
void build(int u,int l,int r)
{
tr[u]={
l,r};
if(l==r) return;
int mid=tr[u].l+tr[u].r>>1;
build(u*2,l,mid);
build(u*2+1,mid+1,r);
}
void pushup(int u)
{
tr[u].v=max(tr[u*2].v,tr[u*2+1].v);
}
int query(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v;
else
{
int v=0,mid=(tr[u].l+tr[u].r)/2;
if(l<=mid) v=max(v,query(u*2,l,r));
if(r>=mid+1) v=max(v,query(u*2+1,l,r));
return v;
}
}
void modify(int u,int x,int v)
{
if(tr[u].l==x&&tr[u].r==x) tr[u].v=v;
else
{
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid) modify(u*2,x,v);
else modify(u*2+1,x,v);
pushup(u);
}
}
int main(void)
{
cin>>m>>p;
build(1,1,m);
int last=0,n=0;
for(int i=0;i<m;i++)
{
char op; cin>>op;
if(op=='Q')
{
int x; cin>>x;
last=query(1,n-x+1,n);
cout<<last<<endl;
}else
{
int x; cin>>x;
modify(1,n+1,(1ll*x+last)%p);
n++;
}
}
return 0;
}
245. 你能回答这些问题吗【单点修改 / 区间内的最大连续字段】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
struct node
{
int l,r;
int sum,tmax,lmax,rmax;
}tr[N*4];
int a[N],n,m;
void push(node& a,node& l,node& r)
{
a.sum=l.sum+r.sum;
a.tmax=max({
l.tmax,r.tmax,l.rmax+r.lmax,l.sum+r.lmax,r.sum+l.rmax,});
a.lmax=max({
l.lmax,l.sum+r.lmax});
a.rmax=max({
r.rmax,r.sum+l.rmax});
}
void pushup(int u)
{
push(tr[u],tr[u*2],tr[u*2+1]);
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={
l,r,a[l],a[l],a[l],a[l]};
else
{
tr[u]={
l,r};
int mid=l+r>>1;
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
}
}
void modify(int u,int x,int v)
{
if(tr[u].l==x&&tr[u].r==x)
{
tr[u]={
x,x,v,v,v,v};
}else
{
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=x) modify(u*2,x,v);
else modify(u*2+1,x,v);
pushup(u);
}
}
node query(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
else
{
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=r) return query(u*2,l,r);
else if(l>mid) return query(u*2+1,l,r);
else
{
auto left=query(u*2,l,r);
auto right=query(u*2+1,l,r);
node res;
push(res,left,right);
return res;
}
}
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
for(int i=0;i<m;i++)
{
int op,x,y; cin>>op>>x>>y;
if(op==1)
{
if(x>y) swap(x,y);
auto temp=query(1,x,y);
cout<<temp.tmax<<endl;
}else modify(1,x,y);
}
return 0;
}
246. 区间最大公约数【区间修改 区间最大公约数】
上述题解的原处
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
LL gcd(LL a,LL b){
return b?gcd(b,a%b):a;}
struct node
{
int l,r;
LL sum,d;
}tr[N*4];
LL n,m,a[N];
void push(node& u,node& l,node& r)
{
u.sum=l.sum+r.sum;
u.d=gcd(l.d,r.d);
}
void pushup(int u)
{
push(tr[u],tr[u*2],tr[u*2+1]);
}
void build(int u,int l,int r)
{
if(l==r)
{
LL b=a[l]-a[l-1];
tr[u]={
l,r,b,b};
}else
{
tr[u]={
l,r};
int mid=l+r>>1;
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
}
}
void modify(int u,int x,LL c)
{
if(tr[u].l==x&&tr[u].r==x)
{
tr[u].sum+=c,tr[u].d+=c;
return;
}
else
{
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=x) modify(u*2,x,c);
else modify(u*2+1,x,c);
pushup(u);
}
}
node query(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
else
{
int mid=(tr[u].l+tr[u].r)/2;
if(mid>=r) return query(u*2,l,r);
else if(l>=mid+1) return query(u*2+1,l,r);
else
{
auto left=query(u*2,l,r);
auto right=query(u*2+1,l,r);
node res;
push(res,left,right);
return res;
}
}
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
for(int i=1;i<=m;i++)
{
char op; cin>>op;
if(op=='C')
{
LL l,r,d; cin>>l>>r>>d;
modify(1,l,d);
if(r+1<=n) modify(1,r+1,-d);
}else
{
int l,r; cin>>l>>r;
node right={
0,0,0,0};
auto left=query(1,1,l);
if(l+1<=n) right=query(1,l+1,r);
printf("%lld\n",labs(gcd(left.sum,right.d)));
}
}
return 0;
}
P3372 【模板】线段树 1【区间修改,区间查询】
#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5+10;
struct node
{
int l,r;
LL sum,add;
}tr[N*4];
LL a[N],n,m;
void pushup(int u)
{
tr[u].sum=tr[u*2].sum+tr[u*2+1].sum;
}
void pushdown(int u)
{
auto &ans=tr[u];
auto &l=tr[u*2];
auto &r=tr[u*2+1];
if(ans.add)
{
l.sum+=(l.r-l.l+1)*ans.add;
r.sum+=(r.r-r.l+1)*ans.add;
l.add+=ans.add;
r.add+=ans.add;
ans.add=0;
}
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={
l,r,a[l],0};
else
{
int mid=(l+r)/2;
tr[u]={
l,r};
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
}
}
void modify(int u,int l,int r,int d)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
tr[u].sum+=1ll*(tr[u].r-tr[u].l+1)*d;
tr[u].add+=d;
}else
{
pushdown(u);
int mid=(tr[u].l+tr[u].r)/2;
if(l<=mid) modify(u*2,l,r,d);
if(r>=mid+1) modify(u*2+1,l,r,d);
pushup(u);
}
}
LL query(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;
else
{
pushdown(u);
LL sum=0;
int mid=(tr[u].l+tr[u].r)/2;
if(l<=mid) sum+=query(u*2,l,r);
if(r>=mid+1) sum+=query(u*2+1,l,r);
return sum;
}
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
for(int i=0;i<m;i++)
{
int op; cin>>op;
if(op==1)
{
int l,r,d; cin>>l>>r>>d;
modify(1,l,r,d);
}else
{
int l,r; cin>>l>>r;
cout<<query(1,l,r)<<endl;
}
}
return 0;
}
P2574 XOR的艺术【区间求1的个数 区间取反】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
struct node
{
int l,r;
int sum,add;
}tr[N*4];
int n,m,a[N];
char s[N];
void pushup(int u)
{
tr[u].sum=tr[u*2].sum+tr[u*2+1].sum;
}
void pushdown(int u)
{
if(tr[u].add)
{
tr[u*2].sum=(tr[u*2].r-tr[u*2].l+1)-tr[u*2].sum;
tr[u*2+1].sum=(tr[u*2+1].r-tr[u*2+1].l+1)-tr[u*2+1].sum;
tr[u*2].add^=1;
tr[u*2+1].add^=1;
tr[u].add=0;
}
}
void build(int u,int l,int r)
{
if(l==r) tr[u]={
l,r,a[l],0};
else
{
tr[u]={
l,r};
int mid=(l+r)/2;
build(u*2,l,mid),build(u*2+1,mid+1,r);
pushup(u);
}
}
void modity(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
tr[u].sum=(tr[u].r-tr[u].l+1)-tr[u].sum;
tr[u].add^=1;
}
else
{
pushdown(u);
int mid=(tr[u].l+tr[u].r)/2;
if(l<=mid) modity(u*2,l,r);
if(r>=mid+1) modity(u*2+1,l,r);
pushup(u);
}
}
int query(int u,int l,int r)
{
if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;
else
{
pushdown(u);
int mid=(tr[u].l+tr[u].r)/2;
int sum=0;
if(l<=mid) sum+=query(u*2,l,r);
if(r>=mid+1) sum+=query(u*2+1,l,r);
return sum;
}
}
int main(void)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>s[i];
for(int i=1;i<=n;i++) a[i]=s[i]-'0';
build(1,1,n);
for(int i=0;i<m;i++)
{
int op,l,r; cin>>op>>l>>r;
if(op==0) modity(1,l,r);
else cout<<query(1,l,r)<<endl;
}
return 0;
}
247. 亚特兰蒂斯【扫描线 求矩阵的面积】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
struct Segment
{
double x,y1,y2;
bool operator< (const Segment &t)const
{
return x<t.x;
}
int k;
}seg[N*2];
struct Node
{
int l,r;
int cnt;
double len;
}tr[N*8];
vector<double>ys;
int find(double y)
{
return lower_bound(ys.begin(),ys.end(),y)-ys.begin();
}
void pushup(int u)
{
if(tr[u].cnt) tr[u].len=ys[tr[u].r+1]-ys[tr[u].l];
else if(tr[u].l!=tr[u].r)
{
tr[u].len=tr[u*2].len+tr[u*2+1].len;
}else tr[u].len=0;
}
void build(int u,int l,int r)
{
tr[u]={
l,r,0,0};
if(l!=r)
{
int mid=(l+r)/2;
build(u*2,l,mid),build(u*2+1,mid+1,r);
}
}
void modify(int u,int l,int r,int k)
{
if(l<=tr[u].l&&tr[u].r<=r)
{
tr[u].cnt+=k;
pushup(u);
}else
{
int mid=(tr[u].l+tr[u].r)/2;
if(l<=mid) modify(u*2,l,r,k);
if(r>mid) modify(u*2+1,l,r,k);
pushup(u);
}
}
int main()
{
int t=1;
while(scanf("%d",&n),n)
{
ys.clear();
for(int i=0,j=0;i<n;i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
seg[j++]={
x1,y1,y2,1};
seg[j++]={
x2,y1,y2,-1};
ys.push_back(y1),ys.push_back(y2);
}
sort(ys.begin(),ys.end());
ys.erase(unique(ys.begin(),ys.end()),ys.end());
build(1,0,ys.size()-2);
sort(seg,seg+n*2);
double res=0;
for(int i=0;i<n*2;i++)
{
if(i>0) res+=tr[1].len*(seg[i].x-seg[i-1].x);
modify(1,find(seg[i].y1),find(seg[i].y2)-1,seg[i].k);
}
printf("Test case #%d\n",t++);
printf("Total explored area: %.2lf\n\n", res);
}
}