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;
}
相关推荐
梦想画家1 小时前
Apache AGE实战指南:从Cypher语法到核心图算法
算法·cypher·apache age
刀法如飞1 小时前
Go数组去重的20种实现方式,AI时代解决问题的不同思路
后端·算法·go
旖-旎2 小时前
深搜练习(N皇后)(10)
c++·算法·深度优先·力扣
Controller-Inversion3 小时前
322. 零钱兑换
算法
头发够用的程序员3 小时前
C++和Python面试经典算法汇总(一)
开发语言·c++·python·算法·容器·面试
淡海水3 小时前
【AI模型】模型量化技术详解
人工智能·算法·机器学习
炸膛坦客3 小时前
嵌入式 - 数据结构与算法:(1-1)数据结构 - 顺序表(Sequential List)
数据结构·算法·嵌入式
水龙吟啸3 小时前
数据结构与算法随机复习–Day1
数据结构·c++·算法
生成论实验室3 小时前
《事件关系阴阳博弈动力学:识势应势之道》第八篇:认知与反思关系——探索、定位与延续
人工智能·算法·架构·知识图谱·创业创新
YaraMemo4 小时前
一文带你区分全局最优解和帕累托最优解
算法·5g·信息与通信·信号处理