AtCoder Beginner Contest 449题解
近期这几套atcoder里最难的一套。
D - Make Target 2
官方
D - Make Target 2 题解由 en_translator 提供
为了方便处理 \(\max(|x|, |y|)\) 这个表达式,我们用 \(|x| > |y|\) 和 \(|x| \leq |y|\) 来计算,最后求和得出答案。
下面,我们将介绍如何计算带有 \(|x| > |y|\) 的数。带有 \(|x| \leq |y|\) 的数也可以同样计算。
当 \(|x| > |y|\) 、 \(\max(|x|, |y|) = |x|\) 时。因此,我们可以遍历 \(L \leq x \leq R\) 内的所有偶数 \(x\) ,并为每个 \(x\) 找出带有 \(|x| > |y|\) 和 \(D \leq y \leq U\) 的 \(y\) 的个数。由于 \(|x| > |y|\) 等价于 \(-|x| < y < |x|\) ,对于固定的 \(x\) ,要计算的整数 \(y\) 在 \(\max(-|x| + 1, D) \leq y \leq \min(|x| - 1, U)\) 之内。这样的 \(y\) 的个数可以表示为 \(\max(0, \min(|x| - 1, U) - \max(-|x| + 1, D) + 1)\) ,每个 \(x\) 的计算时间为 \(O(1)\) 。因此,可以在 \(O(X)\) 个时间内计算出 \(|x| > |y|\) 个,其中 \(X = R - L\) 个。
int main() {
int l, r, d, u;
cin >> l >> r >> d >> u;
ll ans = 0;
// |x| > |y|
for (int x = l; x <= r; x++) {
if (x % 2 == 0) {
int D = max(d, -abs(x) + 1);
int U = min(u, abs(x) - 1);
int C = U - D + 1;
ans += max(C, 0);
}
}
// |x| <= |y|
for (int y = d; y <= u; y++) {
if (y % 2 == 0) {
int L = max(l, -abs(y));
int R = min(r, abs(y));
int C = R - L + 1;
ans += max(C, 0);
}
}
cout << ans << '\n';
}
E - A += v
标答没看懂,所以我选择直接可持久化线段树硬上。
int n,m,q,a[N],cnt[N],mx;
vector<int>vec[N];
int len[N],s[N];
vector<int>tmp[750];
int rt[N];
struct HTree{
struct node{
int ls,rs;
int sum;
}tr[N<<5];
int cnt;
inline void change(int &k,int pre,int l,int r,int x,int y){
k=++cnt;
tr[k]=tr[pre];tr[k].sum++;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)change(tr[k].ls,tr[pre].ls,l,mid,x,y);
if(y>mid)change(tr[k].rs,tr[pre].rs,mid+1,r,x,y);
}
inline int ask(int ll,int rr,int l,int r,int kth){
int x=tr[tr[rr].ls].sum-tr[tr[ll].ls].sum;
if(l==r) return l;
int mid=(l+r)>>1;
if(x>=kth) return ask(tr[ll].ls,tr[rr].ls,l,mid,kth);
return ask(tr[ll].rs,tr[rr].rs,mid+1,r,kth-x);
}
}T;
signed main() {
std::ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
up(i,1,n){
cin>>a[i];
++cnt[a[i]];
mx=max(mx,cnt[a[i]]);
}
up(i,1,m)vec[cnt[i]].push_back(i);
len[0]=s[0]=vec[0].size();
for(int i=1; i<=mx; ++i) {
len[i]=len[i-1]+vec[i].size();
s[i]=s[i-1]+len[i];
}
int k=0;
for(int i=0; i<=mx; ++i) {
for(auto v:vec[i]) {
++k;
T.change(rt[k],rt[k-1],1,m,v,v);
}
}
cin>>q;
while(q--) {
int x;
cin>>x;
if(x<=n)cout<<a[x]<<"\n";
else if(x>mx*m){
if(x%m==0) cout<<m<<"\n";
else cout<<x%m<<"\n";
}
else{
x-=n;
int l=0,r=mx,mid,c=mx;
while(l<=r) {
mid=(l+r)>>1;
if(x<=s[mid]) c=mid,r=mid-1;
else l=mid+1;
}
if(c) x-=s[c-1];
cout<<T.ask(rt[0],rt[len[c]],1,m,x)<<"\n";
}
}
return 0;
}
F - Grid Clipping
正难则反,运用容斥和扫描线。
int H,W,h,w,n;
struct linee {
int l, r, h,mark;
bool operator <(const linee&rhs)const{
if(h == rhs.h)return mark > rhs.mark;
return h < rhs.h;
}
} line[N<<1];
int X[N<<1];
struct node{
int l, r, sum,c,len;
}tr[N<<4];
inline void push_up(int k) {
int l = tr[k].l, r = tr[k].r;
if(tr[k].sum)tr[k].len = X[r + 1] - X[l];
else tr[k].len = tr[lc].len + tr[rc].len;
}
inline void build(int k,int l,int r){
tr[k].l=l;tr[k].r=r;
if(l==r)return;
int mid=(l+r)>>1;
build(lc,l,mid);
build(rc,mid+1,r);
push_up(k);
}
inline void ask(int k, int L, int R, int c) {
int l = tr[k].l, r = tr[k].r;
if(X[l] >= R || X[r + 1] <= L)return;
if(L <= X[l] && X[r + 1] <= R) {
tr[k].sum += c;
push_up(k);
return;
}
ask(lc, L, R, c);
ask(rc, L, R, c);
push_up(k);
}
void solve(){
cin>>H>>W>>h>>w>>n;
int u,v;
if (!n){
cout << (H - h + 1) * (W - w + 1);
return;
}
for(int i=1,x1,y1,x2,y2;i<=n;i++){
cin>>u>>v;
x1=max(1ll,u-h+1);y1=max(1ll,v-w+1);
x2=min(u,H-h+1)+1;y2=min(v,W-w+1)+1;
line[i * 2 - 1] ={x1, x2, y1, 1};
line[i * 2] = {x1, x2, y2,-1};
X[i * 2 - 1] = x1, X[i * 2] = x2;
}
n <<= 1;
sort(line + 1, line + n + 1);
sort(X + 1, X + n + 1);
int tot = unique(X + 1, X + n + 1) - X - 1;
build(1, 1, tot - 1);
int res = 0,pre=0;;
for(int i = 1; i < n; i++) {
ask(1, line[i].l, line[i].r, line[i].mark);
res += tr[1].len * (line[i + 1].h - line[i].h);
}
cout<<(H-h+1)*(W-w+1)-res;
}

浙公网安备 33010602011771号