Codeforces Round 971 (Div. 4) A-G1

A

b-a

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int a,b;
        cin >> a >> b;
        int ans=inf;
        for(int c=a;c<=b;c++) ans=min(ans,c-a+b-c);
        cout << ans << '\n';
    }
    system("color 04");
    return 0;
}

B

模拟,从最后向前遍历找每行的第一个\(#\)记录列数,然后输出

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int n,m=4;
        cin >> n;
        vector<vector<char>> g(n+1,vector<char>(m+1));
        fors(i,1,n){
            fors(j,1,m){
                cin >> g[i][j];
            }
        }
        vector<int> ans;
        forr(i,1,n){
            fors(j,1,m){
                if(g[i][j]=='#'){
                    ans.pb(j);
                }
            }
        }
        fors(i,0,ans.size()-1) cout << ans[i] << " \n"[i==ans.size()-1];
    }
    system("color 04");
    return 0;
}

C

如果最后一次x没到,y到了,仅需要一次 \((t-1)*2+1\)如果最后一次x到了,y没到,需要俩次 \(t*2\),t为到x或者y的步数最大值

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int x,y,k;
        cin >> x >> y >> k;
        int a=(x+k-1)/k,b=(y+k-1)/k;
        int t=max(a,b);
        if(a>b){
            cout << (t-1)*2+1 << '\n';
        }
        else cout << t*2 << '\n';
    }
    system("color 04");
    return 0;
}

D

\(0<=x<=n,0<=y<=1\),可以枚举x的位置,组成直角三角形的点可以有,俩个点在同一列,其余各点都能组成直角三角形,一个点上面或者下面左右俩侧皆有点也可以组成直角三角形。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int n;
        cin >> n;
        vector<vector<int>> a(2,vector<int>(n+1));
        fors(i,1,n){
            int x,y;
            cin >> x >> y;
            a[y][x]=1;
        }
        int ans=0;
        fors(i,0,n){
            if(a[0][i]&&a[1][i]){
                ans+=n-2;
            }
            if(i>=1&&i<=n-1){
                if(a[0][i]&&a[1][i+1]&&a[1][i-1]) ans++;
                if(a[1][i]&&a[0][i+1]&&a[0][i-1]) ans++;
            }
        }
        cout << ans << '\n';
    }
    system("color 04");
    return 0;
}

E

找到一个位置i分割俩侧,使得俩侧差绝对值最小,有俩种做法,一种是二元一次方程找根,一种是凸凹函数用三分。

二元一次方程

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int n,k;
        cin >> n >> k;
        int a=2,b=2*(2*k-1),c=-n*(2*k+n-1);
//        cout << a << ' ' << b << ' ' << c << '\n';
        vector<int> r(2);
        auto get=[&](int a,int b,int c)->vector<int>{
            double t=(double)b*b-(double)4ll*a*c;
            vector<int> ans;
            if(t<0) return ans;
            int ts=sqrt(t);
//            cout << ts << '\n';
            ans.pb((ts-b)/(2*a));
            ans.pb((-b-ts)/(2*a));
            return ans;
        };
        r=get(a,b,c);
        auto sum=[&](int l,int r)->int{
            return (r-l+1)*(l+r)/2;
        };
        int ans=sum(k,k+n-1);
//        cout << r[0] << ' ' << r[1] << '\n';
        for(int i=0;i<2;i++){
            for(int j=r[i]-10;j<=r[i]+10;j++){
                if(j<1||j>n) continue;
                int x1=sum(k,k+j-1);
                int x2=sum(k+j,k+n-1);
                ans=min(ans,abs(x1-x2));
            }
        }
        cout << ans << '\n';
    }
    system("color 04");
    return 0;
}

三分

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int n,k;
        cin >> n >> k;
        auto get=[&](int l,int r)->int{
            return (r-l+1)*(l+r)/2;
        };
        auto check=[&](int i)->int{
            return abs(get(k,k+i-1)-get(k+i,k+n-1));
        };
        int l=1,r=n;
        while(r-l>10){
            int m1=(2*l+r)/3;
            int m2=(l+2*r)/3;
            if(check(m1)<check(m2)) r=m2;
            else l=m1;
        }
        int ans=check(l);
        fors(i,l,r) ans=min(ans,check(i));
        cout << ans << '\n';
    }
    system("color 04");
    return 0;
}

F

一个小技巧破环成链前缀和,可以分为三部分来计算,完整的数组加上左右俩侧,sum+[l,L]+[R,r],算出[l,L]和[R,r]属于第几次偏移量进行前缀和即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}

signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int n,q,sum=0;
        cin >> n >> q;
        // 开一个俩倍长度的前缀和
        vector<int> a(2*n+1),pre(2*n+1);
        fors(i,1,n) cin >> a[i],sum+=a[i],a[i+n]=a[i];
        fors(i,1,2*n) pre[i]=pre[i-1]+a[i];
        while(q--){
            int l,r;
            cin >> l >> r;
            int L=(l%n==0?l:l+(n-l%n));
            L=min(L,r);
            int R=(r%n==0?r:r-r%n+1);
            R=max(R,l);
//            cout << l << ' ' << L << ' ' << R << ' ' << r << '\n';
            int len=r-l+1;
            if(l%n==1) L=-1;
            if(r%n==0) R=-1;
            if(L!=-1){
                len-=(L-l+1);
            }
            if(R!=-1){
                len-=(r-R+1);
            }
            len=max(0ll,len);
            int k=len/n;
//            cout << "len=" << len << '\n';
//            cout << l << ' ' << L << ' ' << R << ' ' << r << '\n';
            int ans=k*sum;
//            cout << "First:ans " << ans << '\n';
            int i=(l+n-1)/n-1,j=(r+n-1)/n-1;
            int res=0;
            int pl=(l%n==0?n:l%n);
            int pr=(r%n==0?n:r%n);
            if(L!=-1){
                int pl=(l%n==0?n:l%n);
                int pr=(L%n==0?n:L%n);
//                cout << "L:" << pl << ' ' << pr << '\n';
                res+=pre[pr+i]-pre[pl+i-1];
            }
//            cout << "L " << res << '\n';
            if(R!=-1){
                int pl=(R%n==0?n:R%n);
                int pr=(r%n==0?n:r%n);
//                cout << "R:" << pl << ' ' << pr << '\n';
                res+=pre[pr+j]-pre[pl+j-1];
            }
//            cout << "R " << res << '\n';
            ans+=res;
            if(l==R&&L==r) ans-=res/2;
            cout << ans << '\n';
        }
    }
    system("color 04");
    return 0;
}

G1

给一个定长的子数组[l,r]求使得[l,r]为连续子数组的最小操作数。有一个小技巧,让\(ai=ai-i\) 就可以转换成区间众数问题,可以使用滑动窗口或者莫队来解决。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
mt19937 rnd(time(0));
#define int long long
typedef tuple<int,int,int> tp;
#define x first
#define y second
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
constexpr int N=200010,mod=1e9+7,inf=1e18;
constexpr double pi=3.1415926535897932384626,eps=1e-5;
const ll  P=rnd()%mod;
#define all(a) a.begin(),a.end()
#define get_count(x) __builtin_popcount(x)
#define fors(i,a,b) for(int i=a;i<=b;i++)
#define forr(i,a,b) for(int i=b;i>=a;i--)
#define pb(x) push_back(x)
int dx[]={0,1,0,-1,1,1,-1,-1,0};
int dy[]={1,0,-1,1,1,-1,-1,1,0};
int random(int l,int r){
    return rand()%r+l;
}
struct node{
    int l,r,id;
}e[N];
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    int __=1;
    cin >> __;
    while(__--){
        int n,k,q;
        cin >> n >> k >> q;
        vector<int> a(n+1),alls;
        map<int,int> cnt,p;
        fors(i,1,n) cin >> a[i],a[i]-=i,alls.pb(a[i]);
        sort(all(alls));
        alls.erase(unique(all(alls)),alls.end());
        fors(i,1,n) a[i]=lower_bound(all(alls),a[i])-alls.begin()+1;
        fors(i,1,q){
            int l,r;
            cin >> l >> r;
            e[i]={l,r,i};
        }
        int len=sqrt(n),res=0;
        auto get=[&](int i)->int{
            return i/len;
        };
        auto cmp=[&](const node& a,const node& b)->bool{
            int i=get(a.l),j=get(b.l);
            if(i!=j) return i<j;
            if(i&1) return a.r<b.r;
            return a.r>b.r;
        };
        auto add=[&](int x)->void{
            cnt[++p[x]]++;
            res=max(res,p[x]);
        };
        auto del=[&](int x)->void{
            if(cnt[p[x]]==1&&p[x]==res) res--;
            cnt[p[x]--]--;
        };
        sort(e+1,e+q+1,cmp);
        vector<int> ans(q+1);
        for(int t=1,i=1,j=0;t<=q;t++){
            auto [l,r,id]=e[t];
            while(i<l) del(a[i++]);
            while(i>l) add(a[--i]);
            while(j<r) add(a[++j]);
            while(j>r) del(a[j--]);
            ans[id]=res;
        }
        fors(i,1,q) cout << max(0ll,k-ans[i]) << '\n';
        // 区间众数
    }
    system("color 04");
    return 0;
}
posted @ 2024-09-04 13:04  sty_stability  阅读(193)  评论(0)    收藏  举报