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("!!!\n") #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; }
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("!!!\n") #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; }