AT_arc210_e [ARC210E] Subset Sum Gaps 题解
紫题!??班上同学场紫?!!
显然没有紫啊 /lengh 一定是虚高了。主观难度青。
这也放模拟赛 T1 啊,要我命啊。
首先考察有没有什么方法可以生成出来这
思考
中途如果完全不做优化的话,最终肯定还是
注意到最终需要判断的是相邻两个的间隔要比某个值大。那么,很显然的,在我们不断
嗯,或者这么说吧,当前处理了一部分,相邻的两个数为
好,那么既然这个时候已经不会做出任何贡献了,维护它们之间的差值已经没有任何意义,将其看作段并合并。对于一个段,维护三个值
于是每次对原集合做翻倍的过程中,再合并一下新产生出来的段。最终得到的段,就是我们的答案,对于相邻的两个段就可以做输出了。
到这里我们已经做完了,但还有一个问题:时间复杂度。这个时间复杂度只是做了一个合并而已,看起来还是
代码非常好写。
::::success[code && submission]
#include<bits/stdc++.h>
#define LL long long
#define UInt unsigned int
#define ULL unsigned long long
#define LD long double
#define pii pair<int,int>
#define pLL pair<LL,LL>
#define pDD pair<LD,LD>
#define fr first
#define se second
#define pb push_back
#define isr insert
#define _i128 __int128
using namespace std;
const int N = 1e5+5;
const LL MOD = 998244353;
struct node{LL l,r,sum;};
LL n,a[N];
vector<node> dp,f;
LL read(){
LL su=0,pp=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')pp=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){su=su*10+ch-'0';ch=getchar();}
return su*pp;
}
bool cmp(node d1,node d2){
return (d1.l<d2.l)||(d1.l==d2.l&&d1.r<d2.r);
}
int main(){
//freopen("subset.in","r",stdin);
//freopen("subset.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)a[i]=read();
dp.pb({0,0,1});
for(int i=1;i<=n;i++){
f=dp;
for(node x:dp)f.pb({x.l+a[i],x.r+a[i],x.sum});
sort(f.begin(),f.end(),cmp);
dp.clear();
for(node x:f){
if(dp.empty()||dp.back().r+(dp.back().r+99)/100<=x.l)
dp.pb(x);//新开一段
else{
dp.back().r=max(dp.back().r,x.r);
dp.back().sum=(dp.back().sum+x.sum)%MOD;
//合并段
}
}
}
cout<<dp.size()-1<<"\n";
node lst;LL now=0;
for(node x:dp){
if(now)cout<<lst.r<<" "<<x.l<<" "<<now<<"\n";
now=(now+x.sum)%MOD,lst=x;
}
return 0;
}
::::
如果本篇题解对你有帮助的话,麻烦你点一个小小的赞,真是太感谢啦!