Submission #493896

#TimeUsernameProblemLanguageResultExecution timeMemory
493896cadmiumsky다리 (APIO19_bridges)C++14
29 / 100
3091 ms10448 KiB
#include <iostream>
#include <tuple>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <stack>
#include <vector>
#include <cmath>

using namespace std;
#pragma optimize ("Ofast")
#pragma target ("avx2")
const int mmax = 100005;
const int nmax = 50005;
const int qmax = 100005;
int n, m;
#define x first
#define y second

namespace DSU {
  stack< pair<int,int> >undostack;
  int dsu[nmax];
  int area[nmax];
  void init() {
    for(int i = 0; i < n; i++) {
      dsu[i]=i;
      area[i]=1;
    }
    while(!undostack.empty())
      undostack.pop();
  }
  int father(int x) {
    return (dsu[x]==x ? x : father(dsu[x]));
  }
  void unite(int x , int y) {
    x = father(x);
    y = father(y);
    if(x == y)
      return;
    if(area[x] > area[y]) {
      swap(x, y);
    }
    dsu[y] = x;
    area[x] += area[y];
    undostack.push({x, y});
  }
  int gettime() {
    return undostack.size();
  }
  void popundo() {
    int x, y;
    tie(x,y) = undostack.top();
    undostack.pop();
    dsu[y] = y;
    area[x] -= area[y];
    return;
  }
  void rollback(int x) {
    while(undostack.size() > x)
      popundo();
  }
  int query(int x) {
    return area[father(x)];
  }
};

int weight[mmax];
int prevweight[mmax];
pair<int, int> edge[mmax];

int rez[qmax];

struct query {
  int type, x, w, ind;
  bool operator < (const query& camsus) const {
    return w<camsus.w || (w==camsus.w && (type%2>camsus.type%2 || (type%2==camsus.type%2 && 
        tuple<int,int,int,int>{type, x, w, ind} < tuple<int,int,int,int>{camsus.type, camsus.x, camsus.w, camsus.ind}  )));
  }
}initq[qmax];

set< query > qs;

static void solve(int l, int r) {
  DSU::init();
  unordered_set< int > used;
  vector< query > inupd;
  for(int i = l; i <= r; i++) {
    if(initq[i].type == 1) {
      used.insert(initq[i].x);
      inupd.push_back(initq[i]);
    }
    else {
      qs.insert(initq[i]);
    } 
  }
  for(auto x:qs) {
    if(x.type == 3) {
      if(used.count(x.x)==0)
        DSU::unite(edge[x.x].x, edge[x.x].y);
      //cout << '+' << edge[x.x].x+1 <<' '<< edge[x.x].y+1 <<' '<< weight[x.x]<< '\n';
    }
    else {
      //cout <<'?'<< x.x+1 << ' '<< x.w <<'\n';
      for(auto upd : inupd) {
        if(upd.ind > x.ind)
          break;
        //cout << "!" << upd.ind <<' '<<upd.type <<' '<<upd.x <<' '<<upd.w <<'\n';
        prevweight[upd.x] = upd.w;
      }
      int inittime=DSU::gettime();
      for(auto e : used) {
        if(prevweight[e]<=x.w) {
          //cout << "+-" << 1+edge[e].x <<' '<< 1+edge[e].y << '\n';
          DSU::unite(edge[e].x, edge[e].y);
        }
        prevweight[e]=weight[e];
      }
      rez[x.ind] = DSU::query(x.x);
      DSU::rollback(inittime);
    }
  }
  for(int i = l; i <= r; i++) {
    if(initq[i].type == 2) {
      qs.erase(qs.find(initq[i]));
    } 
  }
  //cout << '\n';
  //cout << '\n';
}
static void fix(int l, int r) {
  for(int i = l; i <= r; i++) {
    if(initq[i].type==1) {
      //cerr << initq[i].x << ' ' << weight[initq[i].x] <<'\n';
      auto it = qs.find(query{3, initq[i].x, weight[initq[i].x], 0});
      //cerr << (*it).x <<'\n';
      qs.erase(it);
      prevweight[initq[i].x] = weight[initq[i].x] = initq[i].w, 
      qs.insert(query{3, initq[i].x, weight[initq[i].x], 0});
    }
  }
  return;
}

int main() {
  int q;
  cin >> n >> m;
  DSU::init();
  for(int i = 0; i < m; i++) {
    cin >> edge[i].x >> edge[i].y >> weight[i];
    --edge[i].x;
    --edge[i].y;
    weight[i] *= -1; // ca imi convine mai mult cu < decat cu > 
    prevweight[i] = weight[i];
    if(edge[i].x > edge[i].y ) {
      swap(edge[i].x, edge[i].y);
    }
  }
  for(int i = 0; i < m; i++) {
      //cerr << i<< ' ' << weight[i] <<'\n';
    qs.insert(query{3, i, weight[i], 0});
  }
  cin >> q;
  for(int i = 0; i < q; i++) {
    cin >> initq[i].type >> initq[i].x >> initq[i].w;
    initq[i].x--;
    initq[i].w *= -1;
    initq[i].ind=i;
  }
  int buck=1000; // se poate si mai bine
  int l=0,r=-1;
  while(l < q) {
    r=min(q - 1, r + buck);
    solve(l,r);
    fix(l,r);
    l += buck;
  }
  for (int i = 0; i < q; i++) {
    if(initq[i].type == 2)
      cout << rez[i] << '\n';
  }
}
/*
5 5
5 3 6
2 4 49
4 1 44
4 3 74
1 2 85
10
2 2 22
2 2 20
1 3 49
====
2 1 77
1 3 44
1 1 6
====
2 3 49
2 4 31
2 2 54
====
2 2 7

*/

Compilation message (stderr)

bridges.cpp:11: warning: ignoring '#pragma optimize ' [-Wunknown-pragmas]
   11 | #pragma optimize ("Ofast")
      | 
bridges.cpp:12: warning: ignoring '#pragma target ' [-Wunknown-pragmas]
   12 | #pragma target ("avx2")
      | 
bridges.cpp: In function 'void DSU::rollback(int)':
bridges.cpp:59:28: warning: comparison of integer expressions of different signedness: 'std::stack<std::pair<int, int> >::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   59 |     while(undostack.size() > x)
      |                            ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...