题目链接
题目大意
有一个n*m的矩阵,每一行有一个长度为k的数组,数组可以再不越界的情况下在当前行滑动。问你每一列的最大和是多少
解题思路
刚开始的时候,写了一发单调队列,复杂度大概在O(n*m)左右,然后果断断超时了。
正解是:
用一个in和out去存一下,每个数在哪一列开始可以出现,在哪一列结束,这个区间这个数都可以到达,然后就是用set存一下,每一行当前列的最大值,然后用ans统计一下就好了
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
const int N=1e6+5;
pair<int,int>p;
multiset<long long>s[N];
vector<pair<long long,int>>in[N],out[N];
long long ans[N];
int main()
{
int n,m;
long long x;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
{
int k;
scanf("%d",&k);
if(k<m)
{
in[1].push_back(make_pair(0,i));
out[m-k].push_back(make_pair(0,i));
in[k+1].push_back(make_pair(0,i));
out[m].push_back(make_pair(0,i));
}
for(int j=1; j<=k; j++)
{
scanf("%lld",&x);
in[j].push_back(make_pair(x,i));
out[j+m-k].push_back(make_pair(x,i));
}
}
for(int i=1; i<=m; i++)
{
for(auto v:in[i])
{
int a=v.first,b=v.second;
// printf("%d %d\n",a,b);
if(!s[b].empty())
ans[i]-=*s[b].rbegin();
s[b].insert(a);
ans[i]+=*s[b].rbegin();
}
if(i<m)
{
ans[i+1]=ans[i];
for(auto v:out[i])
{
int a=v.first,b=v.second;
ans[i+1]-=*s[b].rbegin();
s[b].erase(s[b].find(a));
if(!s[b].empty())
ans[i+1]+=*s[b].rbegin();
}
}
}
for(int i=1;i<=m;i++)
printf("%lld ",ans[i]);
printf("\n");
return 0;
}