洛谷 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
",ans);
  return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/9647823.html