Xcpc训练题目若干(二)

按位贪心+分讨+答案差分

题意:给定一个序列a以及一个k,构造一个x使(ai ^ x ) <=k的ai数量最多

思路:枚举每一个a,从高位到低位分类讨论

设该位为j , 那么有四种情况

  1. aj=1,k=1
  2. aj=1,k=0
  3. aj=0,k=1
  4. aj=0,k=0

前面的位a与x异或后与k相同,判断该位然后确定x的范围,然后差分

int pre[maxn];
void solve(){
    int n,k;cin>>n>>k;
    vector<int>a(n+1);rep(i,1,n)cin>>a[i];
    rep(i,1,n){
        int l,r;
        int x=0;
        for(int j=20;j>=0;--j){
            if((1ll<<j)&a[i]){
                if((1ll<<j)&k){
                    //aj:1 kj:1 xj:1
                    l=x+(1<<j);
                    r=x+(1<<j+1)-1;
                    pre[l]++;
                    pre[r+1]--;

                    //aj:1 kj:1 xj:0

                }else{
                    //aj:1 kj:0 xj:0 :X

                    //aj:1 kj:0 xj:1
                    x+=(1ll<<j);
                }
            }else{
                if((1ll<<j)&k){
                    //aj:0 kj:1 xj:0
                    l=x;//11010 0 00000
                    r=x+(1<<j)-1; //10010 0 11111
                    pre[l]++;
                    pre[r+1]--;
                    //aj:0 kj:1 xj:1
                    x+=(1ll<<j);
                }else{
                    //aj:0 kj:0 xj:0
                    //aj:0 kj:0 xj:1 :X
                }
            }
        }
        pre[x]++;
        pre[x+1]--;
    }
    int mx=0;
    mx=pre[0];
    for(int i=1;i<=1e7;i++){
        pre[i]+=pre[i-1];
        mx = max(mx,pre[i]);
    }
    cout<<mx<<endl;
}

floyd求最短路径的数目模板题
题意:给定一个无向图,求对于每一对起点和终点,每一个点在其中的权值:(在其最短路径的路径数目)/总最短路径数目 之和

思路:设s[u][v]为u到v的最短路径数目

通过floyd一边更新最短路一边更新路径数目

当d[i][j]>d[i][k]+d[k][j]时,s[i][j]=s[i][k]s[k][j]
当d[i][j]=d[i][k]+d[k][j]时,s[i][j]+=s[i][k]
s[k][j]

初始化时,注意有边的两个点u,v的s[u][v]=1

int d[150][150];
int s[150][150];
void solve(){
    int n,m;cin>>n>>m;

    {
        memset(d,inf,sizeof d);
        rep(i,1,n)d[i][i]=0;
    }
    rep(i,1,m){
        int u,v,w;cin>>u>>v>>w;
        d[u][v]=d[v][u]=w;
        s[u][v]=s[v][u]=1;
    }

    rep(k,1,n){
        rep(i,1,n){
            rep(j,1,n){
                if(i==k||j==k)continue;
                if(d[i][j]>d[i][k]+d[k][j]){
                    d[i][j]=d[i][k]+d[k][j];
                    s[i][j]=s[i][k]*s[k][j];
                }else if(d[i][j]==d[i][k]+d[k][j]){
                    s[i][j]+=(s[i][k]*s[k][j]);
                }
            }
        }
    }

    rep(k,1,n){
        double ans=0;
        rep(i,1,n){
            rep(j,1,n){
                if(i==k||j==k)continue;
                if(d[i][k]+d[k][j]==d[i][j]){
                    ans+=1.0*(s[i][k]*s[k][j])/s[i][j];
                }
            }
        }
        cout<<fixed<<setprecision(3)<<(ans)<<endl;
    }

}

差分+前缀和trick
题意:给定一个长度为n的数组a,求sum[l,r]=s且max(a[l]....a[r])=k的区间数量

思路:
先求出所有最大值小于等于k的答案数量,再求出所有最大值小于等于k-1的答案数量 ,相减即为答案

和等于s可以通过哈希表+前缀和来解决

奇怪的是这题用gp_hash_table或者unordered_map反而比map要慢

int n,s,x;
void solve(){
    cin>>n>>s>>x;
    int A=0,B=0;
    vector<int>a(n+1);
    rep(i,1,n)cin>>a[i];
    vector<pii>ax,bx;
    int l=-1,r=-1;
    rep(i,1,n){
        //<=x
        if(a[i]>x){
            if(l!=-1&&r!=-1){
                ax.pb(mp(l,r));
                l=-1;r=-1;
            }
            continue;
        }else{
            if(l==-1)l=r=i;
            else r=i;
        }
    }
    if(l!=-1&&r!=-1){
        ax.pb(mp(l,r));
        l=-1;r=-1;
    }
    rep(i,1,n){
        //<=x-1
        if(a[i]>x-1){
            if(l!=-1&&r!=-1){
                bx.pb(mp(l,r));
                l=-1;r=-1;
            }
            continue;
        }else{
            if(l==-1)l=r=i;
            else r=i;
        }
    }
    if(l!=-1&&r!=-1){
        bx.pb(mp(l,r));
        l=-1;r=-1;
    }

    for(auto[x,y]:ax){
        map<int,int>mp;
        // gp_hash_table<int,int>mp;
        int pre=0;
        mp[pre]=1;
        rep(i,x,y){
            pre+=a[i];
                A+=mp[pre-s];
            mp[pre]++;
        }
    }
    for(auto[x,y]:bx){
        map<int,int>mp;
        int pre=0;
        mp[pre]=1;
        rep(i,x,y){
            pre+=a[i];
            B+=mp[pre-s];
            mp[pre]++;
        }
    }
    cout<<A-B<<endl;
}
posted @ 2025-08-22 19:17  Marinaco  阅读(9)  评论(0)    收藏  举报
//雪花飘落效果