CF618F-Double Knapsack【结论】
正題
題目鏈接:https://www.luogu.com.cn/problem/CF618F
題目大意
給出大小為nnn,值域為[1,n][1,n][1,n]的兩個可重集合A,BA,BA,B
需要你對它們各求出可重子集使得兩個子集中的數字和相等
輸出方案。
1≤n≤1061\leq n\le 10^61≤n≤106
解題思路
這個值域范圍就很提示性的往鴿籠原理方面考慮。
此題的結論就是一定有連續子序列的解。
先搞一個前綴和A,BA,BA,B,假設An≤BnA_n\leq B_nAn?≤Bn?。
現在我們要求兩個l,rl,rl,r滿足
Ar1?Al1=Br2?Bl2A_{r_1}-A_{l_1}=B_{r_2}-B_{l_2}Ar1???Al1??=Br2???Bl2??
?Ar1?Br2=Al1?Bl2\Rightarrow A_{r_1}-B_{r_2}=A_{l_1}-B_{l_2}?Ar1???Br2??=Al1???Bl2??
現在問題就變為了求兩個相同的Ax?ByA_x-B_yAx??By?.
對于每個AxA_xAx?(x∈[0,n]x\in[0,n]x∈[0,n]),求出一個最大的yyy使得By≤AxB_y\leq A_xBy?≤Ax?
那么顯然有Ax?By∈[0,n?1]A_x-B_y\in[0,n-1]Ax??By?∈[0,n?1],也就是Ax?ByA_x-B_yAx??By?一共只有nnn種取值,而我們有n+1n+1n+1個,所以至少有兩個相同的。
開兩個桶記錄一下出現位置就好了。
時間復雜度O(n)O(n)O(n)
code
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=1e6+10; ll n,a[N],b[N],la[N],lb[N]; signed main() {scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]+=a[i-1];for(ll i=1;i<=n;i++)scanf("%lld",&b[i]),b[i]+=b[i-1];bool f=0;if(a[n]>b[n]){for(ll i=1;i<=n;i++)swap(a[i],b[i]);f=1;}ll ala,alb,ara,arb;for(ll i=0,j=0;i<=n;i++){while(b[j]<=a[i])j++;j--;if(la[a[i]-b[j]]){ala=la[a[i]-b[j]];alb=lb[a[i]-b[j]];ara=i;arb=j;}la[a[i]-b[j]]=i+1;lb[a[i]-b[j]]=j+1;}if(f)swap(ala,alb),swap(ara,arb);printf("%lld\n",ara-ala+1);for(ll i=ala;i<=ara;i++)printf("%lld ",i);printf("\n%lld\n",arb-alb+1);for(ll i=alb;i<=arb;i++)printf("%lld ",i);return 0; }總結
以上是生活随笔為你收集整理的CF618F-Double Knapsack【结论】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么使用磁力下载电影?磁力链接下载工具
- 下一篇: YbtOJ#526-折纸游戏【二分,ha