洛谷 1970 花匠——树状数组

题目:https://www.luogu.org/problemnew/show/P1970

对树状数组有了新的认识。

1.在add()(或x+=(x&-x)的)里不要传进0!!!但是x-=(x&-x)的可以。

2.找大于等于自己的,可以在query()里x+=(x&-x),在add里x-=(x&-x)!

3.离散化之后一定不能按原数组的大小lower_bound了!!!不然真的会错!

  就是如果原来 tp[ ] 有 n 个元素,m=unique(tp+1,tp+n+1)-tp-1; 则之后一定要 lower_bound(tp+1,tp+m+1,a[i])-tp ,不能 tp+n+1 !!!(不知原因)

4.对拍过了2000组数据也不能保证不得30分……(虽然这条和树状数组无关)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m,a[N],tp[N],f0[N],f1[N],dp[N][2],ans;
int rdn()
{
  int ret=0,fx=1; char ch=getchar();
  while(ch>'9'||ch<'0') {if(ch=='-') fx=-1; ch=getchar();}
  while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return ret*fx;
}
int query0(int x)// 0 is ok
{int ret=0;for(;x;x-=(x&-x))ret=max(ret,f0[x]);return ret;}
void add0(int x,int v)
{for(;x<=m;x+=(x&-x)) f0[x]=max(f0[x],v);}
int query1(int x)
{int ret=0;for(;x<=m;x+=(x&-x))ret=max(ret,f1[x]);return ret;}
void add1(int x,int v)
{for(;x;x-=(x&-x)) f1[x]=max(f1[x],v);}
int main()
{
  n=rdn();
  for(int i=1;i<=n;i++) a[i]=tp[i]=rdn();
  sort(tp+1,tp+n+1); m=unique(tp+1,tp+n+1)-tp-1;
  for(int i=1;i<=n;i++) a[i]=lower_bound(tp+1,tp+m+1,a[i])-tp;
  for(int i=1,d;i<=n;i++)
    {
      d=query1(a[i]+1)+1;
      if(d>dp[a[i]][0]) dp[a[i]][0]=d,add0(a[i],d);
      d=query0(a[i]-1)+1;
      if(d>dp[a[i]][1]) dp[a[i]][1]=d,add1(a[i],d);
    }
  for(int i=1;i<=m;i++) ans=max(ans,max(dp[i][0],dp[i][1]));
  printf("%d\n",ans);
  return 0;
}

 

转载于:https://www.cnblogs.com/Narh/p/9647823.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值