2020牛客第二场
比赛过了C D F J,4:59:31过了J 感觉很不错
B题队友卡精度WA了50多发 赛后eps调了个1e-10就过了
E.Exclusive OR
看了题解好像就很容易了,FWT卷19次就能得出答案了。
G.Greater and Greater
讲课的时候学到,给m=40000大概就是要想到bitset,因为如果要mlogm的算法,一般会给1e5的数据。这道题我用题解的方法写了一遍,一开始开了\(n\)个bitset记录状态MLE了,修改成\(m\)种本质不同的bitset之后就好了。然后看别人的过题代码,学到了一种更加优秀的写法。首先我们记答案状态\(ans,ans_{i}=1\)表示以第\(i\)位做起点的窗口能够匹配,我们将\(B\)排序后,考虑逐步移动\(j\),每次将所有\(A_{i}<B_{j}\)的位置状态标为0,剩余的为1,即记录一个临时状态\(now,now_{i}=1表示A中第i位当前尚能匹配\)。显然对于以第\(i\)位做起点的窗口要匹配成功那么第\(i+j\)位必须大于等于\(B_{j}\),所以我们每次将now右移\(j\)位&给答案状态,最后答案状态中为1的就是合法起始点。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 150000;
pair <int,int> a[maxn + 11],b[maxn + 11];
bitset <maxn> now,ans;
int main(){
int n,m;
scanf("%d %d",&n,&m);
for (int i = 1; i <= n; i++) { scanf("%d",&a[i].first); a[i].second = i; }
for (int i = 1; i <= m; i++) { scanf("%d",&b[i].first); b[i].second = i; }
sort(a + 1 , a + 1 + n);
sort(b + 1 , b + 1 + m);
int r = 1;
for (int i = 0; i < n; i++) ans.set(i) , now.set(i);
for (int i = 1; i <= m; i++) {
while (r <= n && a[r].first < b[i].first) { now.reset(a[r].second - 1); r++; }
ans &= (now >> (b[i].second - 1));
}
printf("%d\n" , ans.count());
}
H.Happy Triangle
对于每个询问,我们需要找两个数\(b>a且b-a<x<a+b\)。显然对于任意一个\(b\),所有比它小的数中,最大的\(a\)是最优的。那么我们可以考虑记录这个差值。对于每个数,我记录了集合中第一个严格大于它的数与它的差值。如果没有重复的数,我们查询的时候要找的就是所有差值小于x中数值最大的那个。这个显然可以用线段树进行维护,我们对每个区间记录差值的最小值就可以在线段树上二分找到最右端的符合要求的数值了。现在考虑有重复的值,我是在线段树上打tag,对于每个数值有重复tag为1,没有重复tag为0.这样找差值的时候多判断右子树是否有tag为1的点就可以了。插入删除过程我们用multiset或者set应该都是可以维护的。
#include <bits/stdc++.h>
#define lson rt << 1
#define rson rt << 1 | 1
#define pb emplace_back
#define all(x) (x).begin(),(x).end()
#define pii pair<int,int>
using namespace std;
const int inf = 2e9 + 10;
const int maxn = 2e5;
pii que[maxn + 11];
int cnt[maxn + 11];
vector <int> v;
int tree[4 * maxn + 11],sum[4 * maxn + 11];
void build(int rt,int l,int r) {
tree[rt] = inf; sum[rt] = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(lson , l , mid);
build(rson , mid + 1 , r);
}
void upd(int rt,int l,int r,int pos,int val) {
if (l > pos || r < pos) return;
sum[rt] += val;
if (l == r) return;
int mid = (l + r) >> 1;
upd(lson , l , mid , pos , val);
upd(rson , mid + 1 , r , pos , val);
}
void update(int rt,int l,int r,int pos,int val) {
if (l > pos || r < pos) return;
if (l == r) { tree[rt] = val; return; }
int mid = (l + r) >> 1;
update(lson , l , mid , pos , val);
update(rson , mid + 1 , r , pos , val);
tree[rt] = min(tree[lson] , tree[rson]);
}
int query(int rt,int l,int r,int x) {
if (l == r) {
int val = v[l - 1];
if (tree[rt] < x) return 2 * val + tree[rt];
return 2 * val;
}
int mid = (l + r) >> 1;
if (tree[rson] < x || sum[rson]) return query(rson , mid + 1 , r , x);
return query(lson , l , mid , x);
}
int main(){
int q;
scanf("%d",&q);
for (int i = 1; i <= q; i++) {
scanf("%d %d",&que[i].first , &que[i].second);
v.pb(que[i].second);
}
sort(all(v)); v.erase(unique(all(v)) , v.end());
int n = v.size();
build(1 , 1 , n);
multiset <int> s;
multiset <int> :: iterator it;
for (int i = 1; i <= q; i++) {
int x = lower_bound(all(v) , que[i].second) - v.begin() + 1;
if (que[i].first == 1) {
it = s.upper_bound(x);
if (cnt[x] == 0){
if (it == s.end()) {
if (!s.empty()) {
it--;
int ind = *it;
update(1 , 1 , n , ind , v[x - 1] - v[ind - 1]);
}
}
else if (it == s.begin()) {
int ind = *it;
update(1 , 1 , n , x , v[ind - 1] - v[x - 1]);
}
else {
int r = *it;
it--;
int l = *it;
update(1 , 1 , n , l , v[x - 1] - v[l - 1]);
update(1 , 1 , n , x , v[r - 1] - v[x - 1]);
}
}
s.insert(x);
cnt[x]++;
if (cnt[x] == 2) upd(1 , 1 , n , x , 1);
}
else if (que[i].first == 2) {
it = s.lower_bound(x);
if (cnt[x] >= 2) { }
else if (it == s.begin() && s.size() > 1) update(1 , 1 , n , x , inf);
else {
it--;
int l = *it;
it = s.upper_bound(x);
if (it == s.end()) update(1 , 1 , n , l , inf);
else {
int r = *it;
update(1 , 1 , n , l , v[r - 1] - v[l - 1]);
update(1 , 1 , n , x , inf);
}
}
s.erase(x);
cnt[x]--;
if (cnt[x] == 1) upd(1 , 1 , n , x , -1);
}
else {
if (tree[1] >= que[i].second && !sum[1]) { printf("No\n"); continue; }
if (query(1 , 1 , n , que[i].second) > que[i].second) printf("Yes\n"); else printf("No\n");
}
}
}