Codeforces 920 反图联通块 线段树质因数暴力
A
#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 Mod = 1000000007; int num[205]; int pre[400]; int n; int number; bool check() { for (int i = 1; i <= n; i++) { pre[i] = pre[i - 1] + pre[i]; if (pre[i] < 1) { return false; } } return true; } int main() { int T; cin >> T; while (T--) { cin >> n >> number; for (int i = 1; i <= number; i++) { cin >> num[i]; } for (int i = 1; i <= 200; i++) { for (int j = 1; j <= n; j++) { pre[j] = 0; } for (int j = 1; j <= number; j++) { if (i == 1) { pre[num[j]] += 1; pre[num[j] + 1] += -1; } else { pre[max(1, num[j] - i + 1)] += 1; pre[num[j] + i] += -1; } } if (check()) { cout << i << endl; break; } } } return 0; }
B
#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-8; typedef pair<int, int> pairint; typedef long long ll; typedef unsigned long long ull; //const int maxn = 3e5 + 10; const int maxm = 300; const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}}; //priority_queue<int, vector<int>, less<int>> que; //next_permutation ll mod = 3e7; int le[5005]; int re[5005]; int wait[5005]; int main() { int t; cin >> t; while (t--) { int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d %d", &le[i], &re[i]); } int cur = le[0]; for (int i = 0; i < n; i++) { cur = max(cur, le[i]); if (re[i] >= cur) { wait[i] = cur; cur++; } else { wait[i] = 0; } } for (int i = 0; i < n; i++) { cout << wait[i]; if (i != n - 1) { cout << " "; } } cout << endl; } return 0; }
C
#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 Mod = 1000000007; int num[200005]; int pre[200005]; char f[200005]; int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { scanf("%d", num + i); } scanf("%s", f + 1); for (int i = 1; i < n; i++) { if (f[i] == '1') { pre[i] = pre[i - 1] + 1; } else { pre[i] = 0; } } for (int i = 1; i < n; i++) { if (pre[i] > pre[i + 1]) { sort(num + i - pre[i] + 1, num + i + 2); } } for (int i = 1; i < n; i++) { if (num[i] != i) { cout << "NO" << endl; return 0; } } cout << "YES" << endl; return 0; }
E
把所有点放在一个set里,每次取set中一个顶点,删去,遍历set,删去与此顶点邻接的顶点
因为遍历的过程中有两种结局1.删去某个结点 遍历成功 2.两点之间不存在边 遍历失败
所以遍历的总复杂度为O(n+m) 再加上set的复杂度就是 O((n+m)log)
#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 Mod = 1000000007; set<int> need; map<int, bool> mp[200005]; vector<int> ans; int main() { int n, m; int from, to; cin >> n; for (int i = 1; i <= n; i++) { need.insert(i); } cin >> m; for (int i = 1; i <= m; i++) { scanf("%d %d", &from, &to); mp[from][to] = mp[to][from] = 1; } while (!need.empty()) { int todo = *need.begin(); need.erase(todo); queue<int> que; ans.push_back(0); que.push(todo); while (!que.empty()) { queue<int> shan; int cnt = que.front(); que.pop(); ans.back()++; for (auto i : need) { if (!mp[cnt][i]) { que.push(i); shan.push(i); } } while (!shan.empty()) { need.erase(shan.front()); shan.pop(); } } } cout << ans.size() << endl; sort(ans.begin(), ans.end()); for (auto i : ans) { cout << i << " "; } cout << endl; return 0; }
F
如果知道到N的因数(N%i==0)数量级是N^(1/3)的这道题就很好做了 因为当N=1或者N=2时因数数目等于N 而1e6=2^20 每个数最多被修改7次
所以线段树维护一个最大值 一个sum值 当最大值不大于2时不用修改 大于二时递归下去暴力修改
#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 Mod = 1000000007; ll n, q; int l, r; ll dp[1000005]; struct node { ll maxn, sum; } tree[1200005]; void pushup(int x) { tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum; tree[x].maxn = max(tree[x << 1].maxn, tree[x << 1 | 1].maxn); } void build(int x, ll value, int root = 1, int l = 1, int r = n) { if (l > x || r < x) { return ; } if (l == x && r == x) { tree[root].sum = tree[root].maxn = value; return; } int mid = (l + r) >> 1; if (x <= mid) { build(x, value, root << 1, l, mid); } else { build(x, value, root << 1 | 1, mid + 1, r); } pushup(root); } void update(int xl, int xr, int root = 1, int l = 1, int r = n) { if (l > r || l > xr || r < xl) { return; } if (xl <= l && xr >= r && tree[root].maxn <= 2) { return; } if (l == r) { tree[root].sum = tree[root].maxn = dp[tree[root].sum]; return ; } int mid = (l + r) >> 1; if (xl <= mid) { update(xl, xr, root << 1, l, mid); } if (xr > mid) { update(xl, xr, root << 1 | 1, mid + 1, r); } pushup(root); } ll getsum(int xl, int xr, int root = 1, int l = 1, int r = n) { if (l > r || l > xr || r < xl) { return 0; } if (xl <= l && xr >= r) { return tree[root].sum; } int mid = (l + r) >> 1; return getsum(xl, xr, root << 1, l, mid) + getsum(xl, xr, root << 1 | 1, mid + 1, r); } int main() { cin >> n >> q; ll cnt; for (int i = 1; i <= 1000000; i++) { for (int j = i; j <= 1000000; j += i) { dp[j]++; } } for (int i = 1; i <= n; i++) { scanf("%lld", &cnt); build(i, cnt); } for (int i = 1; i <= q; i++) { int now; ll value; int aim; cin >> now; if (now == 1) { scanf("%d %d", &l, &r); update(l, r); } else { scanf("%d %d", &l, &r); cout << getsum(l, r) << endl; } } return 0; }