洛谷 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; }