首页 > 其他分享 >CF-514-D-单调队列

CF-514-D-单调队列

时间:2024-01-14 16:58:00浏览次数:48  
标签:队列 CF int vector 区间 514 单调 属性

514-D 题目大意

给定\(n\)个人,每个人有\(m\)个属性,第\(i\)个人的第\(j\)个属性值为\(a[i][j]\)。

最多可以执行\(k\)次操作,每次操作选定一个属性,把所有人的该属性减\(1\),求一段最长的区间,满足执行所有操作之后该区间中所有人的所有属性全部为\(0\)。


Solution

转换一下思考方向,求一段最长的区间,满足区间中每项属性的最大值之和不大于\(k\)。

注意到单调性,固定右端点,移动左端点时,区间中所有属性的最大值之和一定是单调不增的。于是可以用双指针来枚举右端点寻找合法的最长区间。

剩下的就是如何快速得到区间中的某项属性的最大值,暴力枚举会使复杂度达到\(O(n^2m)\)级别,对于在双指针的应用场景维护区间最值,这时就应当想到使用单调队列进行优化。

时间复杂度\(O(nm)\)

#include<bits/stdc++.h>
using namespace std;
using ll=long long;

int main() {
    int n,m,k;
    cin>>n>>m>>k;
    vector<vector<int>> a(n,vector<int>(m));
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin>>a[i][j];
        }
    }
    vector<deque<int>> q(m);
    int ans=0;
    vector<int> res(m);
    for(int l=0,r=0;r<n;r++){
        int sum=0;
        for(int j=0;j<m;j++){
            while(!q[j].empty()&&a[q[j].back()][j]<a[r][j]){
                q[j].pop_back();
            }
            q[j].push_back(r);
            sum+=a[q[j].front()][j];
        }
        while(l<=r&&sum>k){
            l++;
            for(int i=0;i<m;i++){
                while(!q[i].empty()&&q[i].front()<l){
                    sum-=a[q[i].front()][i];
                    q[i].pop_front();
                    if(q[i].size()) sum+=a[q[i].front()][i];
                }
            }
        }
        if(r-l+1>ans){
            ans=r-l+1;
            for(int i=0;i<m;i++) res[i]=a[q[i].front()][i];
        }
    }
    for(int i=0;i<m;i++){
        cout<<res[i]<<" ";
    }
    return 0;
}

标签:队列,CF,int,vector,区间,514,单调,属性
From: https://www.cnblogs.com/fengxue-K/p/17963872

相关文章

  • [CF1268D] Invertation in Tournament
    InvertationinTournament题面翻译给定一张\(n\)个点的竞赛图,定义一次操作为选取一个顶点\(v\)并翻转所有以\(v\)为顶点的边的方向。请你判断是否存在一种操作方案使得操作完成后,这个图是强连通的。如果存在,求出最小的操作次数,以及使得操作次数达到最小的操作方案数。其......
  • CF-1920-div2 总结
    1.结果赛时做出:AB(D)赛后做出:CD评分变化:1535->1500rank:45212.赛后总结>1个人评价这次比赛是我寒假的第一次,昨天坐了一天的动车,虽然平稳,但还是有晕车,导致晚上状态不好,个人因素还是有的。最主要的因素还是后一个小时太晕了,D题有个小问题没发现。除此之外,近期开始服用的药物让......
  • 浅谈Linux下傻瓜式磁盘分区工具cfdisk的使用
    对于新手来说,Linux环境下的磁盘分区可能还会存在一些困难。对于熟悉Linux的朋友来说,我们还有fdisk、parted(2TB以上的磁盘分区使用)等磁盘分区工具可以使用。在我们新增磁盘或者在原来磁盘上进行扩容时就会使用到磁盘分区工具,磁盘分区对于整个系统的管理十分重要。1.增加一块容量......
  • 【树上启发式合并】CF1709E XOR Tree
    XORTree\(\mathtt{TAGS}\):树上启发式合并+异或+贪心\(\mathtt{ESTIMATION}\):非常好的启发式合并题目First.如何去除\(0\)路径对于一条路径\(u\tov\),要使其不为\(0\)肯定是将\(\mathtt{LCA}(u,v)\)变为\(2^{30+x}\)最好,这样异或值的第\(30+x\)位一......
  • 矩阵乘法 - CF678D Iterated Linear Function
    CF678DIteratedLinearFunction题意\(f_{i,x}=A\timesf_{i-1,x}+B\)且\(f_{0,x}=x\)求\(f_{n,x}\)。思路这道题的递推关系十分清晰。但由于数据范围大(\(1\leA,B,x\le10^9,1\len\le10^{18}\)),所以这道题只能使用矩阵乘法加速递推。矩阵的构造我们需要构造一个......
  • 模拟 - CF1196C Robot Breakout
    RobotBreakout(CF1196C)思路这道题因为平面极大,暴力枚举每个点肯定会超时。所以,我们不妨从机器人出发。我们可以枚举每个机器人可以执行的操作:位置从\((X_i,Y_i)\)变为\((X_i-1,Y_i)\),即向左走。位置从\((X_i,Y_i)\)变为\((X_i,Y_i+1)\),即向上走。位置从\((X_......
  • 栈和队列
    栈和队列目录栈和队列栈栈的基本定义顺序栈链栈栈栈的基本定义栈是一种特殊的线性表,特点是先进后出栈的操作只能在表的一端进行,出栈和入栈都只能在栈顶(表尾)进行栈的两种实现:顺序栈和链栈顺序栈采用数组,用一个指针指向栈顶双向顺序栈(空间利用率更高)两个栈栈尾是数组的头......
  • CF1016D Vasya And The Matrix Solution
    题目传送门做法因为是异或运算,可以按位考虑。先预处理出行(\(a[i]\))异或和\(suma\),与列(\(b[i]\))的异或和\(sumb\)。如果\(suma\nesumb\),那就说明无解,因为\(suma\)和\(sumb\)最后都代表着整个矩阵的异或和,如果两者不相等,那就说明矛盾,无解。否则就一定......
  • CF414B - Mashmokh and ACM
    思路dp。dp[i][j]表示第i位填j时的方案数ac代码#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;consti64inf=8e18;typedefpair<int,int>pii;constintmod=1e9+7;constintN=2e3+5;intdp[N][N];vector<int>g[N];voi......
  • CF-613-D
    613-D题目大意给定一颗\(n\)个节点的树。\(q\)组询问,每组询问给定\(k\)个点,问至少要删除树中多少个点才能使这\(k\)个点两两不连通,无解则输出\(-1\)。这里\(\sum{k_i}\)的规模大致和\(n\)相当。Solution虚树模板题。暴力的做法是每组询问都对整棵树进行遍树形DP,复杂度为\(......