南京整站優(yōu)化推廣和競(jìng)價(jià)代運(yùn)營(yíng)
題面
分析:
賽時(shí)一直糾結(jié)于與運(yùn)算前綴和不可逆,導(dǎo)致沒(méi)有思路,但是發(fā)現(xiàn)行不通并沒(méi)有及時(shí)思考別的解決辦法導(dǎo)致一條路走到黑,阻礙了自己的思維,在今年的網(wǎng)絡(luò)賽賽時(shí)也是一樣,行不通的時(shí)候就沒(méi)心思去重新想其他方法,這是大忌,以后要改,必須能夠賽時(shí)不斷發(fā)散自己思維,思考多種解決辦法,還有就是賽時(shí)遇到一些自我感覺(jué)麻煩的做法就認(rèn)為對(duì)的可能性不大,就不再去想,要大膽思考各種方法,多嘗試。
雖然與運(yùn)算不可逆,但是拆開(kāi)他的每一位,從前向后記錄他的每一位的1的個(gè)數(shù),這樣就可以進(jìn)行前綴和計(jì)算了,根據(jù)后來(lái)的查詢(xún),只需要查詢(xún)區(qū)間內(nèi)的每一位的1的個(gè)數(shù),只要區(qū)間內(nèi)每一個(gè)數(shù)的二進(jìn)制表示下第 i i i位都是1,那么區(qū)間的與運(yùn)算之和的第 i i i位也就一定是1,這樣就可以求出區(qū)間與運(yùn)算的和,進(jìn)而二分解決。
代碼
#include <bits/stdc++.h>using namespace std;
using ll = long long;const int N = 2e5 + 10;int a[N][32];
int n;
int L;
int k;bool check(int mid) {int cnt = 0;for(int i = 0; i <= 31; i ++) {//cout << a[mid][i] << ' ';if(a[mid][i] - a[L - 1][i] == mid - L + 1) cnt |= (1 << i);}
// cout << mid << ' ' << cnt << endl;return cnt >= k;}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int T;cin >> T;while(T --) {cin >> n;for(int i = 1; i <= n; i ++) {int x;cin >> x;for(int j = 0; j <= 31; j ++) {a[i][j] = a[i - 1][j] + (x >> j & 1);}}int q;cin >> q;while(q --) {cin >> L >> k;int l = L - 1;int r = n;while(l < r) {int mid = l + r + 1 >> 1;if(check(mid)) l = mid;else r = mid - 1;}if(l < L || l > n) cout << "-1 ";else cout << l << " ";//cout << endl;}cout << "\n";}
}