Codeforces Round 900 (Div. 3) - A B C D(差分) E(静态区间查询 + 二分)

传送门

A. How Much Does Daytona Cost?

判断数 k 包不包含在数组里面即可

B. Aleksa and Stack

法一:选定初始数为2, 3,后面的从 4 开始遍历,逐项比较更新答案即可
法二:全奇数即可,因为奇数 + 奇数 = 偶数,奇数 x 3 = 奇数,奇数肯定不能被偶数整除

C. Vasilije in Cacak

等差数列中选 k 个数,最小和为前 k 个数的和,最大和为后 k 个数的和,之间的一定能取到

D. Reverse Madness

思维诈骗题!!!题目具有特殊性
对于式子 $a = min(x, r_i + l_i - x), b = max(x, r_i + l_i - x) $ 表示的区间 [a, b] 即为区间 $[l_i, r_i] $ 中,x 到关于本区间对称位 x1 的子区间。
$l_i \le l_i + r_i - x \le r_i $, $ (x + l_i + r_i - x) / 2 = (l_i + r_i) / 2 $,所以对称
所以所有的翻转都是对称翻转,而且各翻转区间 $[l_i, r_i] $ 之间互不影响
所以利用差分数组统计每个位置上的翻转次数,翻转奇数次输出对称位,偶数次输出本位即可

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
string ss;
int n, k, l[maxm], r[maxm], q;

void solve(){
	cin >> n >> k >> ss;
	for(int i = 1; i <= k; ++ i) cin >> l[i];
	for(int i = 1; i <= k; ++ i) cin >> r[i];
	vector<int> d(n + 10, 0);
	cin >> q;
	while(q--){
		int x;
		cin >> x;
		auto id = lower_bound(r + 1, r + k + 1, x) - r;
		int a = min(x, r[id] + l[id] - x), b = max(x, r[id] + l[id] - x);
		++ d[a]; -- d[b + 1];
	}
	ss = ' ' + ss;
	for(int i = 1; i <= k; ++ i){
		for(int j = l[i]; j <= r[i]; ++ j){
			d[j] += d[j - 1];
			if(d[j] % 2){
				cout << ss[l[i] + r[i] - j ];
			}else cout << ss[j];
		}
	}
	cout << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}

E. Iva & Pav

唯一的问题就是怎么快速的求得区间 [l, r] 的位与值

可以得知从前往后位与,值一定是单调递减的

方法一:线段树区间查询
阿巴阿巴,线段树基础,没啥好说的

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
int n, a[maxm], q;

struct Segment_Tree{//update - range_& + query - range_&
	int n;
	vector<ll> seg, tag;
	Segment_Tree(int cnt) : n(cnt), seg(cnt << 2, 0), tag(cnt << 2, 0){}
	int ls(int p) { return p << 1; }
	int rs(int p) { return p << 1 | 1; }

	void push_up(int p){ seg[p] = seg[ls(p)] & seg[rs(p)]; return ;	}
	void build(int p, int pl, int pr){
		tag[p] = 0;
		if(pl == pr){
			seg[p] = a[pl]; return ;
		}
		int mid = pl + pr >> 1;
		build(ls(p), pl, mid);
		build(rs(p), mid + 1, pr);
		push_up(p);
		return ;
	}

	void addtag(int p, int pl, int pr, ll k){
		tag[p] += k;
		seg[p] += (pr - pl + 1) * k;
		return ;
	}

	void push_down(int p, int pl, int pr){
		if(tag[p]){
			int mid = pl + pr >> 1;
			addtag(ls(p), pl, mid, tag[p]);
			addtag(rs(p), mid + 1, pr, tag[p]);
			tag[p] = 0;
		}
		return ;
	}

	void update(int p, int pl, int pr, int l, int r, ll k){
		if(l <= pl && pr <= r){
			addtag(p, pl, pr, k);
			return ;
		}
		push_down(p, pl, pr);
		int mid = pl + pr >> 1;
		if(l <= mid) update(ls(p), pl, mid, l, r, k);
		if(mid < r) update(rs(p), mid + 1, pr, l, r, k);
		push_up(p);
		return ;
	}

	ll query(int p, int pl, int pr, int l, int r){
		if(l <= pl && pr <= r){
			return seg[p];
		}
		push_down(p, pl, pr);
		ll res = 0; res = ~res;
		int mid = pl + pr >> 1;
		if(l <= mid) res &= query(ls(p), pl, mid, l, r);
		if(mid < r) res &= query(rs(p), mid + 1, pr, l, r);
		return res;
	}
};

void solve(){
	cin >> n;
	vector<ll> f(n + 1);
	for(int i = 1; i <= n; ++ i){
		cin >> a[i];
	}
	Segment_Tree tr(n);
	tr.build(1, 1, n);
	cin >> q;
	while(q --){
		int l, k;
		cin >> l >> k;
		int x = l, y = n, mid;
		while(x <= y){
			mid = (x + y) >> 1;
			if(tr.query(1, 1, n, l, mid) >= k) x = mid + 1;
			else y = mid - 1;
		}
		if(y < l) cout << -1 << ' ';
		else cout << y << ' ';
	}
	cout << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}

方法二:倍增预处理

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e5 + 5, inf = 0x3f3f3f3f, lgn = 20;
const ll INF = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
int n, a[maxm];

void solve(){
	cin >> n;
	vector f(n + 1, vector<int> (lgn, 0));
	vector p(n + 1, vector<int> (lgn, n));
	for(int i = 1; i <= n; ++ i){
		cin >> a[i];
	}
	for(int i = 1; i < n; ++ i){
		f[i][0] = a[i + 1]; p[i][0] = i + 1;
	}
	for(int j = 1; j < lgn; ++ j){
		for(int i = n - (1 << j) + 1; i > 0; -- i){
			f[i][j] = f[i][j - 1] & f[p[i][j - 1]][j - 1];
			p[i][j] = p[p[i][j - 1]][j - 1];
		}
	}
	int q;
	cin >> q;
	while(q --){
		int l, k;
		cin >> l >> k;
		if(a[l] >= k){
			int t = a[l], r = l;
			for(int i = lgn - 1; i >= 0; -- i){
				if((t & f[r][i]) >= k){
					t = t & f[r][i];
					r = p[r][i];
				}
			}
			cout << r << ' ';
		}else{
			cout << -1 << ' ';
		}
	}
	cout << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}
posted @ 2023-09-27 21:18  Qiansui  阅读(69)  评论(0)    收藏  举报