【codevs 3304~3306】水果姐逛水果街系列

这题的坑开了很久了,3305大概是在NOIP之前学线段树的时候AC的,3306也是当时学完LCA后不断提交不断WA,当时基本已弃坑。。。

最近学了树链剖分之后似乎觉得这俩题可做,于是搞了一个晚上,终于搞完了(蒟蒻就是蒟蒻)。。。。。。

3305 这个题是链上的裸线段树,分类讨论比较蛋疼,code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct hp{
      int maxn,minn,cha1,cha2;
}node[800001];
int a[200001],n,m;
void updata(int i)
{
     int c,t; 
     node[i].maxn=max(node[i*2].maxn,node[i*2+1].maxn);
     node[i].minn=min(node[i*2].minn,node[i*2+1].minn);
     t=node[i*2+1].maxn-node[i*2].minn; c=node[i*2].maxn-node[i*2+1].minn;
     node[i].cha1=max(t,max(node[i*2].cha1,node[i*2+1].cha1));
     node[i].cha2=max(c,max(node[i*2+1].cha2,node[i*2].cha2));
}
void build(int i,int l,int r)
{
	 int mid; mid=(l+r)/2;
     if (l==r)
       {
         node[i].maxn=node[i].minn=a[l];
         node[i].cha1=node[i].cha2=0;
         return;
       }
     build(i*2,l,mid);
     build(i*2+1,mid+1,r);
     updata(i);
}
hp queryx(int i,int l,int r,int x,int y)
{
	 int mid=(l+r)/2;
	 if (y<l||x>r) return (hp){-1,100000001,-1,-1};
	 if ((x<=l)&&(y>=r)) return node[i];
     hp tmp1=queryx(i*2,l,mid,x,y),tmp2=queryx(i*2+1,mid+1,r,x,y),tmp;
     tmp.cha1=max(tmp1.cha1,max(tmp2.cha1,tmp2.maxn-tmp1.minn));
     tmp.cha2=max(tmp1.cha2,max(tmp2.cha2,tmp1.maxn-tmp2.minn));
     tmp.minn=min(tmp1.minn,tmp2.minn);
     tmp.maxn=max(tmp1.maxn,tmp2.maxn);
     return tmp;
}
int main()
{
    int i,l,r;
    scanf("%d",&n);
    for (i=1;i<=n;++i)
      scanf("%d",&a[i]);
    build(1,1,n);
    scanf("%d",&m);
    for (i=1;i<=m;++i)
      {
        scanf("%d%d",&l,&r);
        if (l<=r)
          printf("%d\n",queryx(1,1,n,l,r).cha1);
        if (r<l)
          printf("%d\n",queryx(1,1,n,r,l).cha2);
      }
    return 0;
}   
3306 3307 这俩题是一个题,一个带修改,一个不带修改,这里以3306为例,链上的分类讨论比上一道题还蛋疼。

在x链上,用新max和原min更新左边的差;在y链,用原max和新min更新右边的差。code(附一坨调试信息):

#include<iostream>
#include<cstdio>
#include<cstring>
#define inf 2100000000
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
struct hp{
	int top,fat,size,wson,dep;
}tree[200001];
struct hq{
	int maxn,minn,cl/*左买右卖*/,cr/*右买左卖*/;
}seg[800001],ans;
struct ht{
	int u,v;
}a[400001];
int point[200001],next[800001];
int val[200001],plc[200001],f[200001];
int n,m,totw=0,e=0;
void add(int x,int y)
{
	e++; a[e].u=x; a[e].v=y; next[e]=point[x]; point[x]=e;
	e++; a[e].u=y; a[e].v=x; next[e]=point[y]; point[y]=e;
}
void build_tree(int last,int x,int depth)
{
	int i;
	tree[x].fat=last;
	tree[x].dep=depth;
	tree[x].size=1;
	tree[x].wson=0;
	for (i=point[x];i;i=next[i])
	  if (a[i].v!=last)
	    {
	      build_tree(x,a[i].v,depth+1);
	      tree[x].size+=tree[a[i].v].size;
	      if (tree[tree[x].wson].size<tree[a[i].v].size)
	        tree[x].wson=a[i].v;
	    }
}
void build_seg(int now,int tp)
{
	int i;
	tree[now].top=tp;
	plc[now]=++totw; f[totw]=now;
	if (tree[now].wson!=0)
	  build_seg(tree[now].wson,tp);
	for (i=point[now];i;i=next[i])
	  if (a[i].v!=tree[now].wson&&a[i].v!=tree[now].fat)
	    build_seg(a[i].v,a[i].v);
}
void updata(int i)
{
	seg[i].maxn=max(seg[i<<1].maxn,seg[i<<1|1].maxn);
	seg[i].minn=min(seg[i<<1].minn,seg[i<<1|1].minn);
	seg[i].cl=max(seg[i<<1].cl,max(seg[i<<1|1].cl,seg[i<<1|1].maxn-seg[i<<1].minn));
	seg[i].cr=max(seg[i<<1].cr,max(seg[i<<1|1].cr,seg[i<<1].maxn-seg[i<<1|1].minn));
}
void build(int i,int l,int r)
{
	if (l==r)
	  {
	    seg[i].maxn=seg[i].minn=val[f[l]];
	    seg[i].cl=seg[i].cr=0;
	    return;
	  }
	build(lch); build(rch);
	updata(i);
}
void insert(int i,int l,int r,int x,int a)
{
	if (l==x&&l==r)
	  {
	    seg[i].maxn=seg[i].minn=a; seg[i].cl=seg[i].cr=0;
	    return;
	  }
	if (x<=mid) insert(lch,x,a);
	else insert(rch,x,a);
	updata(i);
}
hq query_seg(int i,int l,int r,int x,int y)
{
	hq t,tl,tr;
	if (y<l||x>r) return (hq){-1,inf,-1,-1};
	if (x<=l&&y>=r) {/*cout<<i<<" "<<seg[i].cl<<endl;*/return seg[i];}
	tl=query_seg(lch,x,y); tr=query_seg(rch,x,y);
	t.maxn=max(tl.maxn,tr.maxn); t.minn=min(tl.minn,tr.minn);
	t.cl=max(tl.cl,max(tr.cl,tr.maxn-tl.minn));
	t.cr=max(tl.cr,max(tr.cr,tl.maxn-tr.minn));
	/*cout<<i<<' '<<t.cr<<' '<<tl.cl<<' '<<tr.cl<<' '<<tl.minn<<' '<<tr.maxn<<' '<<l<<" "<<r<<endl;*/
	return t;
}
void query(int x,int y)
{
	int f1=tree[x].top,f2=tree[y].top;
	int lfmax=-inf,rtmin=inf,lfmin=inf,rtmax=-inf,lfc=-inf,rtc=-inf,ansi;
	while (f1!=f2)
	  {
	    if (tree[f1].dep>tree[f2].dep)
	      {
		    ans=query_seg(1,1,n,plc[f1],plc[x]);
		    //cout<<'x'<<':'<<endl;
		    //cout<<plc[f1]<<' '<<plc[x]<<endl;
			lfc=max(lfc,ans.cr); 
			lfmax=max(lfmax,ans.maxn); lfc=max(lfc,ans.maxn-lfmin);
			lfmin=min(lfmin,ans.minn);
			//cout<<lfc<<' '<<lfmax<<' '<<lfmin<<endl<<"------------------------"<<endl;
			x=tree[f1].fat; f1=tree[x].top;
	      }
	    else
	      {
	        ans=query_seg(1,1,n,plc[f2],plc[y]);
	        //cout<<'y'<<':'<<endl;
	        //cout<<plc[f2]<<' '<<plc[y]<<endl;
			rtc=max(rtc,ans.cl); 
			rtmin=min(rtmin,ans.minn); rtc=max(rtc,rtmax-ans.minn);
			rtmax=max(rtmax,ans.maxn); 
			//cout<<rtc<<' '<<rtmax<<' '<<rtmin<<endl<<"------------------------"<<endl;
	        y=tree[f2].fat; f2=tree[y].top;
	      }
	  }
	if (tree[x].dep>tree[y].dep)
	  {
	    ans=query_seg(1,1,n,plc[y],plc[x]);
	    //cout<<'x'<<':'<<endl;
		//cout<<plc[f1]<<' '<<plc[x]<<endl;
		lfc=max(lfc,ans.cr); 
		lfmax=max(lfmax,ans.maxn); lfc=max(lfc,ans.maxn-lfmin);
		lfmin=min(lfmin,ans.minn);
		//cout<<lfc<<' '<<lfmax<<' '<<lfmin<<endl<<"------------------------"<<endl;
	  }
	else
	  {
	    ans=query_seg(1,1,n,plc[x],plc[y]);
	    //cout<<'y'<<':'<<endl;
	    //cout<<plc[x]<<' '<<plc[y]<<endl;
		rtc=max(rtc,ans.cl); 
		rtmin=min(rtmin,ans.minn); rtc=max(rtc,rtmax-ans.minn);
		rtmax=max(rtmax,ans.maxn); 
		//cout<<rtc<<' '<<rtmax<<' '<<rtmin<<endl<<"------------------------"<<endl;
	  }
	ansi=max(lfc,max(rtc,rtmax-lfmin));
	printf("%d\n",ansi); 
}
int main()
{
	int i,x,y,opt;
	scanf("%d",&n); 
	for (i=1;i<=n;++i)
	  scanf("%d",&val[i]);
	for (i=1;i<=n-1;++i)
	  {
	    scanf("%d%d",&x,&y);
	    add(x,y);
	  }
	build_tree(0,1,0);
	build_seg(1,1);
	build(1,1,n);
	scanf("%d",&m);
	for (i=1;i<=m;++i)
	  {
	    scanf("%d%d%d",&opt,&x,&y);
	    if (opt==0)
	      insert(1,1,n,plc[x],y);
	    if (opt==1)
	      query(x,y);
	  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值