zoukankan      html  css  js  c++  java
  • Codeforces 961 容斥叉积判共线 树状数组递增思想题

    A

    B

    C

    D

    给你N个点 问你能不能有两条直线穿过这N个点

    首先假设这N个点是可以被两条直线穿过的 所以两条直线就把这N个点划分成两个集合

    我们取1 2 3三个点这样必定会有两个点在一个集合内 check一下 如果不满足输出NO

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 1e9
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    int n;
    struct Point
    {
            ll x, y;
            Point operator - (const Point& p) const
            {
                    return {x - p.x, y - p.y};
            }
    } p[100005];
    inline bool cross(Point a, Point b)
    {
            return a.y * b.x == a.x * b.y;
    }
    inline bool collinear(int x, int y, int z)
    {
            return cross(p[x] - p[y], p[x] - p[z]);
    }
    int check(int x, int y)
    {
            vector<int> todo;
            for (int i = 1; i <= n; i++)
            {
                    if (!collinear(x, y, i))
                    {
                            todo.pb(i);
                    }
            }
            if (todo.size() <= 2)
            {
                    return 1;
            }
            int now1, now2;
            now1 = todo[0], now2 = todo[1];
            for (auto i : todo)
            {
                    if (!collinear(now1, now2, i))
                    {
                            return 0;
                    }
            }
            return 1;
    }
    int main()
    {
            cin >> n;
            for (int i = 1; i <= n; i++)
            {
                    scanf("%lld %lld", &p[i].x, &p[i].y);
            }
            if (n <= 4)
            {
                    cout << "YES" << endl;
                    return 0;
            }
            int flag = 0;
            flag |= check(1, 2);
            flag |= check(1, 3);
            flag |= check(2, 3);
            if (flag)
            {
                    cout << "YES" << endl;
            }
            else
            {
                    cout << "NO" << endl;
            }
            return 0;
    }
    View Code

    E

    给你N个系列的电视剧 第i个系列有ai集 问你a[i]>=j&&a[j]>=i 这样的对数有多少对

    考察一个递增思想 我们i从1循环到N 删去树状数组里集数为i的 这样下一次求的时候数组里就都是满足条件的了(开始的时候因为条件ai>=1 所以update(i,1))

    (ai=min(ai,n) ai大于N的时候直接可以赋成N)

    #include <bits/stdc++.h>
    #define PI acos(-1.0)
    #define mem(a,b) memset((a),b,sizeof(a))
    #define TS printf("!!!
    ")
    #define pb push_back
    #define inf 1e9
    //std::ios::sync_with_stdio(false);
    using namespace std;
    //priority_queue<int,vector<int>,greater<int>> que; get min
    const double eps = 1.0e-10;
    const double EPS = 1.0e-4;
    typedef pair<int, int> pairint;
    typedef long long ll;
    typedef unsigned long long ull;
    //const int maxn = 3e5 + 10;
    const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
    //priority_queue<int, vector<int>, less<int>> que;
    //next_permutation
    ll n;
    ll num[200005];
    ll t[200005];
    vector<int> number[200005];
    int lowbit(int x)
    {
            return x & (-x);
    }
    void update(int x, ll p)
    {
            while (x <= n)
            {
                    t[x] += p;
                    x += lowbit(x);
            }
            return;
    }
    ll sum(int k)
    {
            ll ans = 0;
            while (k > 0)
            {
                    ans += t[k];
                    k -= lowbit(k);
            }
            return ans;
    }
    int main()
    {
            cin >> n;
            for (int i = 1; i <= n; i++)
            {
                    scanf("%lld", &num[i]);
                    num[i] = min(num[i], n);
                    number[num[i]].pb(i);
                    update(i, 1);
            }
            ll anser = 0;
            for (int i = 1; i <= n; i++)
            {
                    anser += sum(num[i]);
                    for (auto j : number[i])
                    {
                            update(j, -1);
                    }
            }
            for (int i = 1; i <= n; i++)
            {
                    if (num[i] >= i)
                    {
                            anser--;
                    }
            }
            cout << anser / 2 << endl;
            return 0;
    }
    View Code
  • 相关阅读:
    Redis——Redis集群搭建记录 docker方式
    Redis——搭建主从模式 搭建哨兵模式
    Redis——redis的三种集群方式 (转)
    「网易官方」极客战记(codecombat)攻略-山峰-食人魔山谷挖宝-ogre-gorge-gouger
    「网易官方」极客战记(codecombat)攻略-山峰-激流回旋-slalom
    「网易官方」极客战记(codecombat)攻略-山峰_峭壁追逐_crag-tag
    「网易官方」极客战记(codecombat)攻略-沙漠-苦痛之土-harrowland
    「网易官方」极客战记(codecombat)攻略-沙漠-Sarven的宝藏-sarven-treasure
    「网易官方」极客战记(codecombat)攻略-沙漠-Sarven 围困-sarven-siege
    「网易官方」极客战记(codecombat)攻略-沙漠-神圣的雕像-sacred-statue
  • 原文地址:https://www.cnblogs.com/Aragaki/p/8728086.html
Copyright © 2011-2022 走看看