2024CCPC长春邀请赛

E 单调栈 思维

移项得ai−i≥aj−j,bi−i≤bj−ja_i-i\geq a_j-j,b_i-i\leq b_j-jai−i≥aj−j,bi−i≤bj−j

设Ai=ai−i,Bi=bi−iA_i=a_i-i,B_i=b_i-iAi=ai−i,Bi=bi−i
AiA_iAi递增排列,BiB_iBi大的能和后面≤Bi\leq B_i≤Bi的组成连通块,不同连通块max(Bi)max(B_i)max(Bi)从前往后递增

cpp 复制代码
void solve()
{
    int n;cin>>n;
    vector<pii>v(n+1);
    forr(i,1,n){
      cin>>v[i].aa>>v[i].bb;
      v[i].aa-=i,v[i].bb-=i;
    }
    sort(v.begin()+1,v.end(),[&](pii x,pii y){//A_i递增排列
      return (x.aa==y.aa?x.bb>y.bb:x.aa<y.aa);
    });
    vector<int>st;// 每个连通块的max(B_i) 单调递增栈
    st.push_back(1);
    forr(i,2,n){
      if(st.size()){
        if(v[st.back()].bb>=v[i].bb){//能跟栈顶(已有连通块中最大的B)相连
          int tag=st.back(); // 选择 B_i 最大的作为一个联通集的标签 这样向后面连的线多
          st.pop_back();
          while(st.size()&&v[st.back()].bb>=v[i].bb)st.pop_back();//连了这个i点后 前面B>B_i的 也能靠i点和tag成为一个连通块
          // st.push_back(i);
          st.push_back(tag);// 如果放进i的话 直接是一个单减栈
        }else{// v[st.back()].bb<v[i].bb 不能和已有的任何一个连通块相连 
          st.push_back(i);
        }
      }
    }
    cout<<st.size()<<endl;
    
}

F 贪心 堆优化


O(nm)O(nm)O(nm)做法,枚举最后获胜的人,然后枚举每场比赛,这个人比赛的最大值xi+zix_i+z_ixi+zi,其他人在其他比赛尽量小即zjz_jzj平均分配到xj、yjx_j、y_jxj、yj

可以看到其他人的得分重复计算了,可以用堆维护进行优化

cpp 复制代码
const int N = 1e5+5,M=1e5;
const double PI=acos(-1);
const long long mod =998244353, inf = 1e18 ;
struct duel{
  int x,y,z,id;
};
vector<duel>v[N];// 记录每个人参加的比赛
void solve(){
  int n,m;cin>>n>>m;
  forr(i,1,n)v[i].clear();
  set<pii>p;// 用set作为堆 维护其他人的比赛中的得分 方便去掉所讨论的人参加的比赛
  forr(i,1,m){
    int a,b,x,y,z;
    cin>>a>>b>>x>>y>>z;
    v[a].push_back({x,y,z,i});
    v[b].push_back({y,x,z,i});
    // 贪心地想 一个人最大得分x+z 其他人尽量小 就是把其他人的比赛中的z平均分
    int oth=max({(x+y+z+1)/2,x,y});
    p.insert({oth,i});
  }
  vector<int>ans;
  forr(i,1,n){// 讨论每个人参加的比赛
    vector<pii>tmp;
    int oth_mx=0,now_mx=0;
    for(auto [x,y,z,id]:v[i]){
      int oth=max({(x+y+z+1)/2,x,y});// 去掉参加的 保留没参加的
      p.erase({oth,id});
      tmp.push_back({oth,id});
      
      oth_mx=max(oth_mx,y);
      now_mx=max(now_mx,x+z);

    }
    if(p.size()){
      oth_mx=max(oth_mx,(int)(prev(p.end())->first));
    }
    if(now_mx>oth_mx)ans.push_back(i);
    for(auto x:tmp){
      p.insert(x);
    }
  }
  cout<<ans.size()<<endl;
  for(auto x:ans)cout<<x<<' ';cout<<endl;
}
相关推荐
珂朵莉MM4 小时前
第七届全球校园人工智能算法精英大赛-算法巅峰赛产业命题赛第3赛季优化题--启发式算法+操作因子设计
人工智能·算法
CS创新实验室5 小时前
CS实验室行业报告:AI算法工程师就业分析报告
人工智能·算法
XiYang-DING5 小时前
【LeetCode】Hash | 136.只出现一次的数字
算法·leetcode·哈希算法
wayz115 小时前
Day 3:逻辑回归与分类预测
算法·分类·逻辑回归
tankeven6 小时前
HJ176 【模板】滑动窗口
c++·算法
网域小星球6 小时前
C 语言从 0 入门(十二)|指针与数组:数组名本质、指针遍历数组
c语言·算法·指针·数组·指针遍历数组
冰糖拌面6 小时前
二叉树遍历-递归、迭代、Morris
算法
碧海银沙音频科技研究院7 小时前
虚拟机ubuntu与windows共享文件夹(Samba共享)解决WSL加载SI工程满卡问题
人工智能·深度学习·算法
CoovallyAIHub7 小时前
ICLR 2026 | VLM自己学会调检测器:VTool-R1用强化学习教视觉模型使用工具推理
算法·架构·github