Tinkoff, SQRT D

#include <bits/stdc++.h> #define fastIO ios_base::sync_with_stdio(0); cin.tie(0); #define forn(i, a, b) for (int i = (a); i < (b); i++) #define ford(i, a, b) for (int i = (b)-1; i >= (a); i--) #define all(x) (x).begin(),(x).end() #define fi first #define se second #define szof(x) ((int)(x).size()) #define rsz resize #define lb lower_bound #define ub upper_bound #define INF (int)1e9 #define INFL (long long)1e18 #define re return #define pb push_back #define mp make_pair #define mt make_tuple #define ll long long #define ld long double #define PII pair<int,int> #define VI vector<int> #define VVI vector<vector <int> > #define VVLL vector<vector <long long> > #define VLL vector <long long> #pragma GCC optimize("unroll-loops") #pragma GCC optimize("Ofast") #define debug(x) cout << #x << " is " << x << '\n'; #define debug2(x) cout << #x << " is : "; for (auto elem : x) { cout << elem << " " ;} cout << "\n"; using namespace std; const int MAXN = 1e5; int n,m; vector <int> g[MAXN]; short int cnt[1000][MAXN+1]; //Счетчик для тежлых вершин. Сколько вершин цвета от 1 до MAXN соседи тяжелой вершины int color[MAXN]; // Цвет int ans; int len; //sqrt N int num[MAXN]; // сжатый номер для тяжелой вершины void solve() { vector <int> deg(n); // Степень vector <int> big; for (int i = 0; i < n; i++) { deg[i] = szof(g[i]); if (deg[i] >= len) { //тяжелая вершина big.pb(i); } } sort(all(big)); for (int i = 0; i < szof(big); i++) { int v = big[i]; num[v] = i; //Типа сжимаем вершины, чтобы cnt был размера не MAXN (попытка ускориться, не всегда же доступ к массиву O(1)) } //Предпосчет, запускаеся от вершин и смотрим сколько вершин другого цвета for (int v = 0; v < n; v++) { for (auto u : g[v]) { if (color[u] != color[v]) { ans++; } if (deg[v] >= len) { cnt[num[v]][color[u]]++; //Опа, наша v - тяжелая. Помечаем что у тяжелой есть такой цвет в соседях } } } ans /= 2; for (auto v : big) { sort(all(g[v]), [&](int a, int b) { return deg[a] > deg[b]; }); // сортируем вершины по убыванию степени. У тяжелых вершин убираем ребра в более легкие, у которых степень меньше корня while(!g[v].empty() && deg[g[v].back()] < len) { g[v].pop_back(); } } int q; cin >> q; for (int i = 0; i < q;i++) { int c,col; cin >> c >> col; c--; // запросик if (deg[c] < len) { // легкая for (auto u : g[c]) { // идем по соседям. Сначала прибавляем обратно цвет, который у вершины сейчас if (color[u] == color[c]) { ans++; } if (color[u] == col) { // и отнимаем новый ans--; } if (deg[u] >= len) { // нашли соседа тяжелую вершину cnt[num[u]][color[c]]--; cnt[num[u]][col]++; } } color[c] = col; // обнова } else { ans += cnt[num[c]][color[c]]; // вершина тяжелая, идем по ребрам в другие тяжелые for (auto u : g[c]) { cnt[num[u]][color[c]]--; cnt[num[u]][col]++; } color[c] = col; ans -= cnt[num[c]][color[c]]; } cout << ans << "\n"; // опа ответ } // Ну и че ты TL получаешь, падла? } int main() { fastIO; cin >> n >> m; len = sqrt(n); forn(i, 0, n) { cin >> color[i]; } for (int i = 0; i < m; i++) { int a,b; cin >> a >> b; a--;b--; g[a].pb(b); g[b].pb(a); } solve(); return 0; }

Be the first to comment

You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.