有无大佬帮我看看这篇代码,cf超时,洛谷能过
查看原帖
有无大佬帮我看看这篇代码,cf超时,洛谷能过
1215295
discretely楼主2024/11/12 12:03

我本来是nloglog的,cf用树状数组和神秘优化卡过去了。


后面想了一下线段树上二分的写法,应该是nlogn的,但是发现cf上竟然过不了,还得加点什么神秘优化才能刚刚卡过去。


但是洛谷是能过得,最慢的耗时3.30s左右,求大佬们解答? 还是说这是我没用树状数组的缘故?还是说cf评测机有问题

#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
#define int long long
#define endl '\n'
#define lc u<<1
#define rc u<<1|1
#define mid ((l+r)>>1)
const int N=1e5+10;
int ls[N*45],rs[N*45],sum[N*45];
int root[N],tot;
int l1,r1,l2,r2;

int val[N*4];
int e;
int a[N];
int c[N],v[N];
int n,m;
int len;
void pushup(int u){
    val[u]=val[lc]+val[rc];
}
void build(int u,int l,int r){
    if(l==r){
        val[u]=v[l];return;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    pushup(u);
}
void change(int u,int l,int r,int x,int k){
    if(l==r){
        val[u]=k;return;
    }
    if(x<=mid) change(lc,l,mid,x,k);
    else change(rc,mid+1,r,x,k);
    pushup(u);
}
void update(int &u,int v,int l,int r,int x,int k){
    u=++tot;
    ls[u]=ls[v],rs[u]=rs[v],sum[u]=sum[v]+k;
    if(l==r) return;
    if(x<=mid) update(ls[u],ls[v],l,mid,x,k);
    else update(rs[u],rs[v],mid+1,r,x,k);
}
int que(int u,int l,int r,int x,int y){
    if(x<=l&&r<=y) return val[u];
    int num=0;
    if(x<=mid) num+=que(lc,l,mid,x,y);
    if(y>mid) num+=que(rc,mid+1,r,x,y);
    return num;
}
int query(int v,int l,int r,int x,int y){
    if(!v) return 0;
    if(x<=l&&r<=y) return sum[v];
    int num=0;
    if(x<=mid) num+=query(ls[v],l,mid,x,y);
    if(y>mid) num+=query(rs[v],mid+1,r,x,y);
    return num;
}
void askr(int &l,int &r){
    if(l+1==r) return;
    int m=(l+r)>>1;
    int num=0;
    for(int i=1;i<=len;++i) num+=query(root[a[i]],1,n,e,m);
    if(num==m-e+1){
        l=m;
        askr(l,r);
    }
    else if(num<m-e+1){
        r=m;
        askr(l,r);
    }
}
void askl(int &l,int &r){
    //cout<<l<<' '<<r<<endl;
    if(l+1==r) return;
    int m=(l+r)>>1;
    int num=0;
    for(int i=1;i<=len;++i) num+=query(root[a[i]],1,n,m,e);
    //cout<<m<<' '<<num<<endl;
    if(num==e-m+1){
        r=m;
        //if(l==r) return;
        askl(l,r);
    }
    else if(num<e-m+1){
        l=m;
        //if(l==r) return;
        askl(l,r);
    }
}
//  while(l1+1<r1){
//     int m=(l1+r1)>>1;
//     int num=0;
//     for(int i=1;i<=k;++i) num+=query(root[a[i]],1,n,m,x);
//     if(num<x-m+1) l1=m;
//     else r1=m;
// }
void solve(){
    tot=0;
	cin>>n>>m;
    for(int i=1;i<=n;++i) root[i]=0;
    for(int i=1;i<=n;++i){
        cin>>c[i];
        update(root[c[i]],root[c[i]],1,n,i,1);
    }
    for(int i=1;i<=n;++i) cin>>v[i];
    build(1,1,n);
    for(int i=1;i<=m;++i){
        int op;cin>>op;
        if(op==1){
            int p,x;cin>>p>>x;
            update(root[c[p]],root[c[p]],1,n,p,-1);
            c[p]=x;
            update(root[c[p]],root[c[p]],1,n,p,1);
        }
        else if(op==2){
            int p,x;cin>>p>>x;
            change(1,1,n,p,x);
            v[p]=x;
        }
        else{
            cin>>e>>len;
            for(int i=1;i<=len;++i) cin>>a[i];
            l1=0,r1=e+1;
            askl(l1,r1);
            l2=e-1,r2=n+1;
            askr(l2,r2);
            //cout<<endl;
            //cout<<r1<<' '<<l2<<endl;
            cout<<que(1,1,n,r1,l2)<<endl;
            //cout<<r1<<' '<<l2<<endl;
        }
        //cout<<1<<endl;
    }

}

signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int _=1;
    cin>>_;
	while(_--){
		solve();
	}
	return 0;
}
2024/11/12 12:03
加载中...