求为什么线段树换树状数组就过了?!
查看原帖
求为什么线段树换树状数组就过了?!
462558
ziyistudy楼主2024/7/29 07:46

开始不会树状数组维护修改区间max,所以用线段树。然后死调不出来,发现题解区都是树状数组,就换了个树状数组,然后就过了?!

求原因。

线段树40pts:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll MOD=1e9+7;
// head
const int N=1e6+5;int MAXN=0;
struct node
{
    int pos,val,minn,maxn;
}a[N],b[N];
bool cmp(node p,node q) {return p.maxn<q.maxn;}
bool cmp1(node p,node q) {return p.val<q.val;}
bool cmp2(node p,node q) {return p.pos<q.pos;}
int dp[N];
int ls(int x) {return x<<1;}
int rs(int x) {return x<<1|1;}
struct Seg
{
    int ans[N<<2];
    void push_up(int dir)
    {
        ans[dir]=max(ans[ls(dir)],ans[rs(dir)]);
    }
    void modify(int dir,int l,int r,int x,int k)
    {
        if(l==x&&r==x) {ans[dir]=k;return ;}
        int mid=(l+r)>>1;
        if(x<=mid) modify(ls(dir),l,mid,x,k);
        else modify(rs(dir),mid+1,r,x,k);
        push_up(dir); 
    }
    int query(int qx,int qy,int x,int y,int dir)
    {
        int sum=0;
        if(qx<=x&&y<=qy) return ans[dir];
        int mid=(x+y)>>1;
        if(qx<=mid) sum=query(qx,qy,x,mid,ls(dir));
        if(qy>mid) sum=max(sum,query(qx,qy,mid+1,y,rs(dir)));
        return sum;
    }
}tree;
void CDQ(int l,int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1;
    CDQ(l,mid);
    sort(a+l,a+mid+1,cmp);
    sort(a+mid+1,a+r+1,cmp1);
    int i=l,j=mid+1;
    while(j<=r)
    {
        while(i<=mid&&a[i].maxn<=a[j].val){
            tree.modify(1,1,MAXN,a[i].val,dp[a[i].pos]);
            i++;
        }
        dp[a[j].pos]=max(dp[a[j].pos],tree.query(1,a[j].minn,1,MAXN,1)+1);
        j++;
    }
    for(int k=l;k<i;k++) tree.modify(1,1,MAXN,a[k].val,0);
    sort(a+l,a+r+1,cmp2);
    CDQ(mid+1,r);
}
signed main() 
{
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++) a[i].pos=i,dp[i]=1;
    for(int i=1;i<=n;i++) {cin>>a[i].val;a[i].maxn=a[i].minn=a[i].val;MAXN=max(MAXN,a[i].val);}
    for(int i=1;i<=m;i++) {
        int x,y;cin>>x>>y;
        a[x].minn=min(a[x].minn,y);
        a[x].maxn=max(a[x].maxn,y);
    }

    CDQ(1,n);

    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
    cout<<ans<<endl;
}

树状数组100pts:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll MOD=1e9+7;
// head
const int N=1e6+5;int MAXN=0;
struct node
{
    int pos,val,minn,maxn;
}a[N],b[N];
bool cmp(node p,node q) {return p.maxn<q.maxn;}
bool cmp1(node p,node q) {return p.val<q.val;}
bool cmp2(node p,node q) {return p.pos<q.pos;}
int dp[N];
int c[N];
void modify(int x,int v)
{
    for(;x<=MAXN;x+=x&(-x))
    c[x]=max(c[x],v);
}
int ask(int x)
{
    int ret=0;
    for(;x;x-=x&(-x))
    ret=max(c[x],ret);
    return ret;
}
void clear(int x)
{
    for(;x<=MAXN;x+=x&(-x))
    c[x]=0;
}
void CDQ(int l,int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1;
    CDQ(l,mid);
    sort(a+l,a+mid+1,cmp);
    sort(a+mid+1,a+r+1,cmp1);
    int i=l,j=mid+1;
    while(j<=r)
    {
        while(i<=mid&&a[i].maxn<=a[j].val){
            modify(a[i].val,dp[a[i].pos]);
            i++;
        }
        dp[a[j].pos]=max(dp[a[j].pos],ask(1,a[j].minn)+1);
        j++;
    }
    for(int k=l;k<i;k++) tree.modify(1,1,MAXN,a[k].val,0);
    sort(a+l,a+r+1,cmp2);
    CDQ(mid+1,r);
}
signed main() 
{
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++) a[i].pos=i,dp[i]=1;
    for(int i=1;i<=n;i++) {cin>>a[i].val;a[i].maxn=a[i].minn=a[i].val;MAXN=max(MAXN,a[i].val);}
    for(int i=1;i<=m;i++) {
        int x,y;cin>>x>>y;
        a[x].minn=min(a[x].minn,y);
        a[x].maxn=max(a[x].maxn,y);
    }

    CDQ(1,n);

    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
    cout<<ans<<endl;
}
2024/7/29 07:46
加载中...