zoukankan      html  css  js  c++  java
  • ABC207

    B

    题意:一个容器,一开始有A个青球,现在你可以进行一种操作:向容器里面放B个青球和C个红球,问是否能够通过t次操作使得青球的个数少于红球个数的D倍

    方法:

    n次操作后,箱子里有(A + nB)个青,(nC)个红球,要求((A + nB)/(nC) le D ightarrow A +nBle nDC ightarrow A le n(DC-B))

    所以只需要判断(DC - B)是否大于0,如果(DC-B>0)那么一定存在一个n满足条件,否则一定不存在

    #include<iostream>
    using namespace std;
    
    int main(){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        int t = c * d - b;
        if(t <= 0){
            cout << -1;
            return 0;
        }
        
        if(a / t * t == a) cout << a / t;
        else cout << a / t + 1;
    }
    

    C

    题意:给你N个区间,类型包括([l, r], [l, r), (l, r], (l, r)), 找出所有有交集的区间i, j, 满足(1 le i < j le N)的个数

    方法:按左端点排序,保存每个区间的位置,(O(n^2))

    #include<iostream>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    
    struct node{
        int l, r, t;
        
        bool operator<(const node &n){
            return l < n.l;
        }
    };
    
    vector<node> v;
    
    int check(int i, int j){
        if(v[i].r != v[j].l) return v[i].r > v[j].l;
        if(v[j].t == 3 || v[j].t == 4) return 0;
        return v[i].t == 1 || v[i].t == 3;
    }
    
    int main(){
        int n;
        cin >> n;
        for(int i = 0; i < n; i ++){
            int t, l, r;
            cin >> t >> l >> r;
            v.push_back({l, r, t});
        }
        
        sort(v.begin(), v.end());
        
        int res = 0;
        for(int i = 0; i < n; i ++)
            for(int j = i + 1; j < n; j ++)
                res += check(i, j);
        
        cout << res;
    }
    

    BONUS: N <= 1e5

    方法:预处理所有区间,由于区间端点都是整数,所以对于开区间,可以+-0.5处理,这样处理不会使原本相交的区间不相交原本不相交的区间相交,按左端点升序排序所有区间,遍历每一个区间i然后二分后面的最大的满足左端点 <= i的右端点的区间位置

    #include<iostream>
    #include<vector>
    #include<algorithm>
    
    using namespace std;
    
    struct node{
        double l, r;
        
        bool operator<(const node &n){
            return l < n.l;
        }
    };
    
    vector<node> v;
    int n;
    
    int find(double x, int l, int r){
        if(l > r) return -1;
        
        while(l < r){
            int mid = l + r + 1 >> 1;
            if(v[mid].l <= x) l = mid;
            else r = mid - 1;
        }
        
        if(v[l].l <= x) return l;
        return -1;
    }
    
    int main(){
        cin >> n;
        for(int i = 0; i < n; i ++){
            double l, r;
            int t;
            cin >> t >> l >> r;
            if(t == 3 || t == 4) l += 0.5;
            if(t == 2 || t == 4) r -= 0.5;
            v.push_back({l, r});
        }
        
        sort(v.begin(), v.end());
        
        int res = 0;
        for(int i = 0; i < n; i ++){
            int j = find(v[i].r, i + 1, n - 1);
            if(j == -1) continue;
            res += j - i;
        }
        
        cout << res;
    }
    

    D

    题意:两个点集S,T,判断能否通过旋转和平移使S,T一样

    方法:求形心(重心),将两个集合均平移到源点,然后以s1去找T中的满足dist(s1) == dist(ti)的点,这个时候认为找到了T中可能的s1的对应点,求出s1应该旋转多少度到ti,然后将s中的所有点都旋转这个角度,看能不能和t匹配即可

    注意:如果s1就是重心的话,那么平移后s1就是(0, 0), 如果实际上S和T可以匹配的话,这个时候由于s1在t中的对应点也为原点,此时旋转角为0,而实际上却需要旋转才可以匹配的话,这个时候会误判为No,所以出现这种情况,swap(s1, s2)就行

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 110;
    
    #define P pair<double, double>
    #define x first
    #define y second
    
    vector<P> s, t;
    int n;
    
    void read(vector<P> &v){
        double sx = 0, sy = 0;
        for(int i = 0; i < n; i ++){
            double a, b;
            cin >> a >> b;
            v.push_back({a, b});
            sx += a, sy += b;
        }
        
        double gx = sx / n, gy = sy / n;
        for(auto &t : v){
            t.x -= gx;
            t.y -= gy;
        }
    }
    
    double dist(P &t){
        return t.x * t.x + t.y * t.y;
    }
    
    double angle(P &p1, P &p2){
        return atan2(p2.y, p2.x) - atan2(p1.y, p1.x);
    }
    
    int equal(double a, double b){
        return fabs(a - b) <= 1e-6;
    }
    
    P rotate(P &p, double a){
        double x = p.x * cos(a) - p.y * sin(a);
        double y = p.x * sin(a) + p.y * cos(a);
        return {x, y};
    }
    
    int main(){
        cin >> n;
        read(s), read(t);
        
        for(int i = 0; i < s.size(); i ++)
            if(s[i].x != 0.0 || s[i].y != 0.0){
                swap(s[0], s[i]);
                break;
            }
        
        for(auto i : t){
            double d2 = dist(i);
            if(equal(d2, dist(s[0]))){
                double a = angle(s[0], i); // 弧度
                int cnt = 0;
                for(auto j : s){
                    P p = rotate(j, a);
                    for(auto k : t)
                        if(equal(k.x, p.x) && equal(k.y, p.y))
                            cnt ++;
                }
                
                if(cnt == n){
                    cout << "Yes";
                    return 0;
                }
            }
        }
        
        cout << "No";
    }
    
  • 相关阅读:
    Qt笔记之 信号和槽
    Qt笔记之 坐标系
    Qt笔记之 QPushButton
    点双连通
    bzoj 2179 FFT快速傅立叶
    bzoj 4128 矩阵求逆
    bzoj 3924 点分
    bzoj 1076 状态压缩最优期望
    bzoj 3143 随机游走
    bzoj 4084 双旋转字符串
  • 原文地址:https://www.cnblogs.com/tomori/p/15477787.html
Copyright © 2011-2022 走看看