生活随笔
收集整理的這篇文章主要介紹了
2022百度之星程序设计大赛 - 初赛 - 第二场 1001 和
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
problem
solution
題意:
- 給出長為n的序列,q次詢問區間是否存在<=k個數之和>=x。
- n,q < 1e5, k <10.
思路:
- 因為要和>=x,所以讓和盡可能大,即判斷區間中最大的k個數之和是否大于x即可。
- 即區間最大,倒數第2大,倒數第3大,倒數第k大之和即可,k<10,可以暴力。
- 對于區間從小到大第x個數(即第x大的數),主席樹板子即可,復雜度O(qklogn)。
#include<bits/stdc++.h>
using namespace std
;
const int N
= 100000 + 5;int a
[N
], b
[N
], rt
[N
* 20], ls
[N
* 20], rs
[N
* 20], sum
[N
* 20];
int n
, k
, tot
, sz
, ql
, qr
, x
, q
, T
;
int kk
, xx
;void Build(int& o
, int l
, int r
){o
= ++ tot
;sum
[o
] = 0;if(l
== r
) return;int m
= (l
+ r
) >> 1;Build(ls
[o
], l
, m
);Build(rs
[o
], m
+ 1, r
);
}
void update(int& o
, int l
, int r
, int last
, int p
){o
= ++ tot
;ls
[o
] = ls
[last
];rs
[o
] = rs
[last
];sum
[o
] = sum
[last
] + 1;if(l
== r
) return;int m
= (l
+ r
) >> 1;if(p
<= m
) update(ls
[o
], l
, m
, ls
[last
], p
);else update(rs
[o
], m
+ 1, r
, rs
[last
], p
);
}
int query(int ss
, int tt
, int l
, int r
, int k
){if(l
== r
) return l
;int m
= (l
+ r
) >> 1;int cnt
= sum
[ls
[tt
]] - sum
[ls
[ss
]];if(k
<= cnt
) return query(ls
[ss
], ls
[tt
], l
, m
, k
);else return query(rs
[ss
], rs
[tt
], m
+ 1, r
, k
- cnt
);
}
void work(){scanf("%d%d", &ql
, &qr
);int len
= (qr
-ql
+1);int res
= 0;for(int i
= len
; i
> len
-kk
; i
--){int ans
= query(rt
[ql
- 1], rt
[qr
], 1, sz
, i
); res
+= b
[ans
];}if(res
>= xx
)printf("Y\n");else printf("N\n");
}
int main(){scanf("%d%d%d%d", &n
, &q
, &kk
, &xx
);for(int i
= 1; i
<= n
; i
++) scanf("%d", a
+ i
), b
[i
] = a
[i
];sort(b
+ 1, b
+ n
+ 1);sz
= unique(b
+ 1, b
+ n
+ 1) - (b
+ 1);tot
= 0;Build(rt
[0],1, sz
);for(int i
= 1; i
<= n
; i
++)a
[i
] = lower_bound(b
+ 1, b
+ sz
+ 1, a
[i
]) - b
;for(int i
= 1; i
<= n
; i
++)update(rt
[i
], 1, sz
, rt
[i
- 1], a
[i
]);while(q
--)work();return 0;
}
總結
以上是生活随笔為你收集整理的2022百度之星程序设计大赛 - 初赛 - 第二场 1001 和的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。