返回顶部

山海经&&Atcoder Alternating String (线段树)

  • 前言:为什么把他们放在一起?因为我发现把pushup向上回溯放结构体类型函数里比较方便
    并且这两题确实也有相同思想

山海经

image
image

这题分三种情况

  1. 左子树前缀和+右子树前缀和
    2.右子树后缀和 与 右总区间+左子树
    3.左区间最大子段 与 右区间最大子段 与 左后缀与右前缀
  • 特别要注意的事项
    1.LONGLONG
    2.是否有等于号(因为要取最小的i,j注意相同情况取最小)
点击查看代码
#include<bits/stdc++.h>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int N=200010;
int m,n,k,p,a[N];
struct tree
{ int ls=-INT_MAX,rs=-INT_MAX,ms=-INT_MAX;
  int l,r,sum; 
  int ml=-INT_MAX,mr=-INT_MAX;
  int ll,rr;
} t[N<<2];
tree push_up(tree x,tree y)
{  
    tree z;
    z.l=x.l;
	z.r=y.r;
	z.sum=x.sum+y.sum;
	if(x.ls<x.sum+y.ls)
	{
		z.ls=x.sum+y.ls;
		z.rr=y.rr;
	}
	else {z.ls=x.ls;z.rr=x.rr;}
	
	if(y.rs<=y.sum+x.rs)
	{
		z.rs=y.sum+x.rs;
		z.ll=x.ll;
	}
	else 
	{
		z.rs=y.rs;
		z.ll=y.ll;	
	}
	z.ms=x.ms;
	z.ml=x.ml;
	z.mr=x.mr;
	if(x.rs+y.ls>z.ms)
	{
		z.ms=x.rs+y.ls;
		z.ml=x.ll;
		z.mr=y.rr;	
	}
	if(z.ms<y.ms)
	{
		z.ms=y.ms;
		z.ml=y.ml;
		z.mr=y.mr;			
	}
  return z; 
}
void bt(int rt,int l,int r)
{
	t[rt].l=l;t[rt].r=r;
	if(l==r)
	{
		t[rt].sum=a[l];
		t[rt].ml=t[rt].mr=t[rt].ll=t[rt].rr=l;
		t[rt].ls=t[rt].rs=t[rt].ms=a[l];
		return;
	}
	int mid=(t[rt].l+t[rt].r)>>1;
	bt(lid,l,mid);
	bt(rid,mid+1,r);
	t[rt]=push_up(t[lid],t[rid]);
}
tree query(int rt,int l,int r)
{
	if(l<=t[rt].l&&t[rt].r<=r)
	{
		return t[rt];
	}
	int mid=(t[rt].l+t[rt].r)>>1;
	if(r<=mid) return query(lid,l,r);
	if(l>mid) return query(rid,l,r);
	return push_up(query(lid,l,r),query(rid,l,r)); 	
}
int main()
{ 
//  freopen("hill.in","r",stdin);
//  freopen("hill.out","w",stdout);
  scanf("%d%d",&n,&m);
  for (int i=1;i<=n;i++)
  scanf("%d",&a[i]);
  bt(1,1,n);
//  for(int i=1;i<=30;i++)
//  {
//      cout<<i<<' '<<t[i].l<<' '<<t[i].r <<' '<<t[i].ms<<endl;	 
//  }
  for (int i=1;i<=m;i++)
  { 
  	int x,y;
    scanf("%d%d",&x,&y);
    tree tmp=query(1,x,y);
    printf("%d %d %d\n",tmp.ml,tmp.mr,tmp.ms);
  }
  return 0;
}

Alternating String

链接

这题只需要维护一下左端点值和右端点值即可
用异或和维护

点击查看代码
#include <bits/stdc++.h>
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
int len,q;
const int N=500000;
int a[N+5];
struct tree
{
	int l,r,lz;bool y;
	int stw,enw;
}t[N<<2];
tree pushup(tree x,tree y)
{	
	tree z;
	z.l=x.l;z.r=y.r;
	z.stw=x.stw;z.enw=y.enw;
	if(x.y&&y.y&&x.enw!=y.stw)
	{
		z.y=1;
	}
	else z.y=0;	
	return z;
}
void pushdown(int rt)
{
	if(t[rt].lz)
	{
		int lz=t[rt].lz;
		t[rt].lz=0;
		t[lid].lz^=lz;
		t[rid].lz^=lz;
		t[lid].stw^=lz;t[lid].enw^=lz;
		t[rid].stw^=lz;t[rid].enw^=lz;
	}
}
void bt(int rt,int l,int r)
{
	t[rt].l=l;t[rt].r=r;
	if(l==r)
	{
//		t[rt].sum=a[l];
		t[rt].y=1;
		t[rt].stw=t[rt].enw=a[l];
		return;
	}
	int mid=(l+r)>>1;
	bt(lid,l,mid);
	bt(rid,mid+1,r);
	t[rt]=pushup(t[lid],t[rid]);
}
void update(int rt,int l,int r)
{
	if(l<=t[rt].l&&t[rt].r<=r)
	{
		t[rt].lz^=1;
		t[rt].stw^=1;t[rt].enw^=1;
		return;
	}
	pushdown(rt);
	int mid=(t[rt].l+t[rt].r)>>1;
	if(l<=mid)update(lid,l,r);
	if(r>mid)update(rid,l,r);
	t[rt]=pushup(t[lid],t[rid]);
}
tree query(int rt,int l,int r)
{
	if(l<=t[rt].l&&t[rt].r<=r)
	{
		return t[rt];
	}
	pushdown(rt);
	int mid=(t[rt].l+t[rt].r)>>1;
	int val=0;
	if(l<=mid&&r>mid)
	{
		return pushup(query(lid,l,r),query(rid,l,r));
	}
	else if(l<=mid)return query(lid,l,r);
	else if(r>mid)return query(rid,l,r);	
}
int main()
{
	scanf("%d%d",&len,&q);
	for(int i=1;i<=len;i++)
	{
		scanf("%1d",&a[i]);
	}
	int k=1,aa,b;
	bt(1,1,len);
	for(int i=1;i<=q;i++)
	{
		scanf("%d%d%d",&k,&aa,&b);
		if(k==1)
		{
			//fanzhuan
			update(1,aa,b);
		}else
		{
			if(query(1,aa,b).y)
			{
				cout<<"Yes"<<endl;
			}else 
			{
				cout<<"No"<<endl;
			}
		}
	}
	return 0;
}
/*
5 6
10100
2 1 3
2 1 5
1 1 4
2 1 5
1 3 3
2 2 4

*/
posted @ 2024-02-22 11:38  wlesq  阅读(15)  评论(0编辑  收藏  举报