2024北京市赛补题

原题链接

好难...用的技巧和算法很多

K 贪心 桶

直观想 每次最小的乘二 乘二就是左移 每次把最高位最小的乘二

枚举二进制位 把所有数整到一个最高二进制位上 如果还有剩的k就同步变大 用桶维护最高二进制位 2e5*30

cpp 复制代码
vector<int>b[40];
void solve(){
	int n,k;cin>>n>>k;
  vector<int>a(n+1);
  // ,b(n+1,0);
  forr(i,1,n){
    cin>>a[i];
  }
  
  forr(i,1,n){
    int tp=a[i],cnt=0;
    while (tp)
    {
      cnt++;
      tp>>=1;
    }
    b[cnt].push_back(a[i]);
  }
  int ans=0,sm=0;
  forr(i,0,30){
    sort(b[i].begin(),b[i].end());
    if(b[i].size()==n){
      int tm=k/n;
      k%=n;
      int psm=0,ssm=0;
      forr(j,0,k-1)(psm+=b[i][j]%mod)%=mod;
      forr(j,k,b[i].size()-1)(ssm+=b[i][j]%mod)%=mod;
      (ans+=(psm*qpow(2,tm+1)%mod+ssm*qpow(2,tm)%mod)%mod)%=mod;
      break;
    }
    for(auto x:b[i]){
      if(k>0)b[i+1].push_back(x<<1),k--;
      else b[i+1].push_back(x);
    }
    if(k==0){
      forr(j,i+1,30){
        for(auto x:b[j])(ans+=x%mod)%=mod;
      }
      break;
    }
  }
  cout<<ans<<endl;
  /* 
    int ans=0,pre=0,id=n;
    forr(i,1,n-1){
      int dis=b[i+1]-b[i];
      cout<<dis<<' '<<k<<endl;
      (ans+=a[i])%=mod;
      if(dis>0){
        int sft=min(k,dis*i);
        k-=sft;
        (ans*=qpow(2,sft))%=mod;// 合并成一块了 不知道其中如何分配
      }
      if(k==0){
        id=i;
        break;
      }
    }
    
    forr(i,id,n)ans+=a[i];
    (ans*=qpow(2,k))%=mod;
    cout<<ans<<endl;  
  */
  
  
  // int ans=0,psm=0,ssm=0;
  // forr(i,1,k)(psm+=a[i])%=mod;;
  // forr(i,k+1,n)(ssm+=a[i])%=mod;
  // ans= (qpow(2,tm+1)*psm%mod+qpow(2,tm)*ssm%mod)%mod;
  // cout<<ans<<endl;
}  

D LCA找两点之间的路径 判断点是否在路径上

如果本次点在相邻两点的路径上 那么这个点不是目标经典

用LCA找两点间路径

cpp 复制代码
const int N = 2e5+10,M=1e5;
const double PI=acos(-1),eps=1e-7;
const long long mod =1e9+7, inf = 2e18 ;
int n,m,q;
int fa[N][35],dep[N];
int b[N];
vector<int>g[N];
void dfs(int now,int f){// O(nlogn)
  fa[now][0]=f;
  dep[now]=dep[f]+1;
  for(int i=1;(1<<i)<=dep[now];i++){
    fa[now][i]=fa[fa[now][i-1]][i-1];
  }

  for(auto x:g[now]){
    if(x==f)continue;
    dfs(x,now);
  }
}
int LCA(int x,int y){
  if(dep[x]<dep[y])swap(x,y);
  
  reforr(i,0,20){
    if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
  }
  if(x==y)return x;
  reforr(i,0,20){
    if(fa[x][i]!=fa[y][i]){
      x=fa[x][i],y=fa[y][i];
    }
  }
  return fa[x][0];
}
bool isanc(int x,int tar){// 确定tar是否为x的祖先
  reforr(i,0,20){
    if(dep[fa[x][i]]>=dep[tar])x=fa[x][i];// x上跳
  }

  return x==tar;
}
bool check(int p){// 判断now是不是目标景点 是1 不是0
  /*
    now是目标景点:不在相邻两点的路径上
  */
  if(p==1||p==m)return 1;// 不是两边都有点 不能确定是路过的点 那就算作目标景点
  int lp=b[p-1],rp=b[p+1],now=b[p];// 看now是否在lp rp的路上
  int f=LCA(lp,rp);

  if(dep[f]>dep[now])return 1; //now比f深度浅 now不可能在路上
  // dep[f]<=dep[now] now可能在路上
  // lp rp 通过f连成一条路 如果now在路上 now是lp或rp的一个祖先
  if(isanc(lp,now)||isanc(rp,now))return 0;
  else return 1;
}
void solve(){
  cin>>n>>m>>q;
  forr(i,1,n-1){
    int u,v;cin>>u>>v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  dfs(1,0);
  forr(i,1,m)cin>>b[i];
  int ans=0;
  forr(i,1,m)ans+=check(i);
  while (q--)
  {
    int p,w;cin>>p>>w;
    // 一个点和相邻两点状态相关
    // 消除原来的状态
    if(p-1>=1)ans-=check(p-1);
    if(p+1<=m)ans-=check(p+1);
    ans-=check(p);
    //添加新的状态
    b[p]=w;
    if(p-1>=1)ans+=check(p-1);
    if(p+1<=m)ans+=check(p+1);
    ans+=check(p);
    cout<<ans<<endl;
  }
  
}  
相关推荐
机器人零零壹19 分钟前
技术白皮书:iRobotCAM如何解决机器人激光切割应用中的核心难点,从CAD离线编程到双目视觉定位与轨迹自适应提升复杂空间曲线切割的精度、效率与柔性化水平
人工智能·算法
布莱克6052 小时前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
ZhengEnCi3 小时前
大模型的分类到底怎么分:从基础模型到推理模型、从通用到专用的完整图谱
算法
取名真是4 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法
罗西的思考4 小时前
【轻量化复刻大模型 / KIMI K3】KDA 模块交互式演示
人工智能·算法·机器学习
沫璃染墨6 小时前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互
nm_zfyjt6 小时前
信息流广告投放优化实践:线索成本评估模型与转化链路重构(家装建材案例)
算法·重构·内蒙古朋友圈广告服务商·内蒙古朋友圈获客
xiaoye-duck7 小时前
《C++ 项目:手写大模型接入 SDK》DeepSeek接口设计(下):流式响应实现和测试
开发语言·网络·c++·语言模型
w_zero_one7 小时前
算法--构造
java·数据结构·算法
其实防守也摸鱼8 小时前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php