結果

問題 No.2293 無向辺 2-SAT
ユーザー laoidnlaoidn
提出日時 2023-05-06 03:08:49
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 9,884 bytes
コンパイル時間 6,012 ms
コンパイル使用メモリ 247,352 KB
実行使用メモリ 11,476 KB
最終ジャッジ日時 2024-11-23 14:50:55
合計ジャッジ時間 79,375 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
10,496 KB
testcase_01 AC 5 ms
11,476 KB
testcase_02 AC 2 ms
10,860 KB
testcase_03 WA -
testcase_04 AC 641 ms
5,740 KB
testcase_05 AC 535 ms
5,248 KB
testcase_06 AC 785 ms
5,248 KB
testcase_07 TLE -
testcase_08 AC 2,110 ms
5,740 KB
testcase_09 TLE -
testcase_10 TLE -
testcase_11 AC 555 ms
5,736 KB
testcase_12 AC 1,660 ms
5,632 KB
testcase_13 AC 461 ms
5,248 KB
testcase_14 WA -
testcase_15 WA -
testcase_16 AC 596 ms
5,736 KB
testcase_17 AC 470 ms
5,760 KB
testcase_18 AC 899 ms
5,632 KB
testcase_19 AC 316 ms
5,248 KB
testcase_20 WA -
testcase_21 WA -
testcase_22 WA -
testcase_23 WA -
testcase_24 WA -
testcase_25 WA -
testcase_26 WA -
testcase_27 WA -
testcase_28 WA -
testcase_29 WA -
testcase_30 WA -
testcase_31 WA -
testcase_32 WA -
testcase_33 WA -
testcase_34 WA -
testcase_35 WA -
testcase_36 WA -
testcase_37 WA -
testcase_38 WA -
testcase_39 WA -
testcase_40 WA -
testcase_41 WA -
testcase_42 WA -
testcase_43 WA -
testcase_44 WA -
testcase_45 WA -
testcase_46 WA -
testcase_47 WA -
testcase_48 WA -
testcase_49 WA -
testcase_50 WA -
testcase_51 WA -
testcase_52 WA -
testcase_53 WA -
testcase_54 WA -
testcase_55 WA -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
#include <iostream>
#include <vector>
using namespace atcoder;
using ll = long long;
using ld = long double;
using P = pair<int, int>;
using Graph = vector<vector<int>>;
using vi = vector<int>;
using vl = vector<long>;
using vll = vector<long long>;
using vb = vector<bool>;
using vvi = vector<vi>;
using vvl = vector<vl>;
using vvb = vector<vb>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vc = vector<char>;
using vvc = vector<vc>;
using vs = vector<string>;
using pii = pair<long long, long long>;
using mint = modint1000000007;
const long double EPS = 1e-10;
const long long INF = 1e18;
const long double PI = acos(-1.0L);
#define reps(i, a, n) for (ll i = (a); i < (ll)(n); i++)
#define rep(i, n) for (ll i = (0); i < (ll)(n); i++)
#define rrep(i, n) for (ll i = (1); i < (ll)(n + 1); i++)
#define repd(i, n) for (ll i = n - 1; i >= 0; i--)
#define rrepd(i, n) for (ll i = n; i >= 1; i--)
#define ALL(n) begin(n), end(n)
#define fore(i, a) for (auto &i : a)
#define IN(a, x, b) (a <= x && x < b)
#define IN(a, x, b) (a <= x && x < b)
#define INIT                        \
  std::ios::sync_with_stdio(false); \
  std::cin.tie(0);
template <class T>
inline T CHMAX(T &a, const T b) {
  return a = (a < b) ? b : a;
}
template <class T>
inline T CHMIN(T &a, const T b) {
  return a = (a > b) ? b : a;
}
#include <algorithm>  // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <bitset>     // bitset
#include <cctype>     // isupper, islower, isdigit, toupper, tolower
#include <cstdint>    // int64_t, int*_t
#include <cstdio>     // printf
#include <deque>      // deque
#include <iostream>   // cout, endl, cin
#include <map>        // map
#include <queue>      // queue, priority_queue
#include <set>        // set
#include <stack>      // stack
#include <string>     // string, to_string, stoi
#include <tuple>      // tuple, make_tuple
#include <unordered_map>  // unordered_map
#include <unordered_set>  // unordered_set
#include <utility>        // pair, make_pair
#include <vector>         // vector
using namespace std;
ll GCD(ll m, ll n) {
  // ベースケース
  if (n == 0) return m;

  // 再帰呼び出し
  return GCD(n, m % n);
}

ll minlong = 0;

long long Power(long long a, long long b, long long m) {
  long long p = a, Answer = 1;
  for (int i = 0; i < 63; i++) {
    ll wari = (1LL << i);
    if ((b / wari) % 2 == 1) {
      Answer = (Answer * p) % m;  // 「a の 2^i 乗」が掛けられるとき
    }
    p = (p * p) % m;
  }
  return Answer;
}

// a ÷ b を m で割った余りを返す関数
long long Division(long long a, long long b, long long m) {
  return (a * Power(b, m - 2, m)) % m;
}

// nCr mod 1000000007 を返す関数
long long nCk(ll n, ll r) {
  const long long M = 1000000007;

  // 手順 1: 分子 a を求める
  long long a = 1;
  for (int i = 1; i <= n; i++) a = (a * i) % M;

  // 手順 2: 分母 b を求める
  long long b = 1;
  for (int i = 1; i <= r; i++) b = (b * i) % M;
  for (int i = 1; i <= n - r; i++) b = (b * i) % M;

  // 手順 3: 答えを求める
  return Division(a, b, M);
}
using Interval = pair<ll, ll>;
// nCk mint を返す関数。
ll modnCk(ll n, ll r) {
  ll a = 1;
  for (ll i = n; i > n - r; i--) {
    a *= i;
    a /= n + 1 - i;
  }
  return a;
}
// 終点時間でsortをかけるのに必要(区間スケジューリング問題など)
bool cmp(const Interval &a, const Interval &b) { return a.second < b.second; }
vll dycstra(vector<vector<pair<ll, ll>>> G, ll N, ll K) {
  vb kaku(N, false);
  vll cur(N, INF);
  cur[K] = 0;
  priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> Q;
  Q.push(make_pair(cur[K], K));
  while (!Q.empty()) {
    ll pos = Q.top().second;
    Q.pop();
    if (kaku[pos]) continue;
    kaku[pos] = true;
    for (ll i = 0; i < G[pos].size(); i++) {
      ll nex = G[pos][i].first;
      ll cost = G[pos][i].second;
      if (cur[nex] > cur[pos] + cost) {
        cur[nex] = cur[pos] + cost;
        Q.push(make_pair(cur[nex], nex));
      }
    }
  }
  return cur;
}
ll f(ll x, vll &memo, ll D, vector<pair<ll, ll>> &X) {
  if (memo[x] != -1) return memo[x];
  if (x < D) return 0;
  ll y = x - D;
  ll x1, x2, y1, y2;
  tie(x1, y1) = X[y];
  tie(x2, y2) = X[x];
  ll cost = abs(x1 - x2) + abs(y1 - y2);
  ll res = cost + f(y, memo, D, X);
  return memo[x] = res;
}
template <class T>
struct BIT {
  int n;                  // 要素数
  vector<T> bit[600000];  // データの格納先
  BIT(int n_) { init(n_); }
  void init(int n_) {
    n = n_ + 1;
    for (int p = 0; p < 2; p++) bit[p].assign(n, 0);
  }
  void add_sub(int p, int i, T x) {
    for (int idx = i; idx < n; idx += (idx & -idx)) {
      bit[p][idx] += x;
    }
  }
  void add(int l, int r, T x) {  // [l,r) の区間で加算
    add_sub(0, l, -x * (l - 1));
    add_sub(0, r, x * (r - 1));
    add_sub(1, l, x);
    add_sub(1, r, -x);
  }
  T sum_sub(int p, int i) {
    T s(0);
    for (int idx = i; idx > 0; idx -= (idx & -idx)) {
      s += bit[p][idx];
    }
    return s;
  }
  T sum(int i) { return sum_sub(0, i) + sum_sub(1, i) * i; }
  // sum'(i)=sum(i)-x(l-i)+xi(sum'(i)は加算後の合計値sum(i)測酸前の合計値)
  T query(int l, int r) { return sum(r - 1) - sum(l - 1); }
  // 任意の区間を計算することが可能これは[l,r)の区間和を計算している。
  int lower_bound(T w) {  // a_1 + a_2 + ... + a_x >= w となるような最小の x
                          // を求める(ただし a_i >= 0)
    if (w <= 0) {
      return 0;
    } else {
      int x = 0, r = 1;
      while (r < n) r = r << 1;
      for (int len = r; len > 0;
           len = len >> 1) {  // 長さlenは1段下るごとに半分に
        if (x + len < n && bit[x + len] < w) {  // 採用するとき
          w -= bit[x + len];
          x += len;
        }
      }
      return x + 1;
    }
  }
};
vll BFS(vvll &G, ll &x) {
  vll cut(G.size(), INF);
  queue<ll> Q;
  Q.push(x);
  cut[x] = 0;
  while (!Q.empty()) {
    ll a = Q.front();
    Q.pop();
    rep(i, G[a].size()) {
      if (cut[G[a][i]] > cut[a] + 1) {
        cut[G[a][i]] = cut[a] + 1;
        Q.push(G[a][i]);
      }
    }
  }
  return cut;
}
template <class Abel>
struct UnionFind {
  vector<int> par;
  vector<int> rank;
  vector<Abel> diff_weight;
  vector<int> siz;
  UnionFind(int n = 1, Abel SUM_UNITY = 0) { init(n, SUM_UNITY); }

  void init(int n = 1, Abel SUM_UNITY = 0) {
    par.resize(n);
    rank.resize(n);
    diff_weight.resize(n);
    siz.resize(n);
    for (int i = 0; i < n; ++i)
      par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY, siz[i] = 1;
  }

  int root(int x) {
    if (par[x] == x) {
      return x;
    } else {
      int r = root(par[x]);
      diff_weight[x] +=
          diff_weight[par[x]];  // 累積和をとることで重みがつけられる。
      return par[x] = r;
    }
  }

  Abel weight(int x) {
    root(x);                // 経路圧縮
    return diff_weight[x];  // 重みを返す
  }

  bool issame(int x, int y) {
    return root(x) == root(y);  // 通常時も同じ
  }

  // weight(y) - weight(x) = w となるように merge する
  bool merge(int x, int y, Abel w) {
    // x と y それぞれについて、 root との重み差分を補正
    w += weight(x);
    w -= weight(y);
    // x と y の root へ (x と y が既につながっていたら false を返すようにした)
    x = root(x);
    y = root(y);
    if (x == y) return false;

    // rank[x] >= rank[y] となるように x と y を swap (それに合わせて w
    // も符号反転します)これはUnion by
    // rankと呼ばれ根の高さをO(logN)で抑えられる手法である。
    if (rank[x] < rank[y]) swap(x, y), w = -w;

    // y (のroot) を x (のroot)
    // の下にくっつける(高さが低い方の根付き木を高いほうに併合する)
    if (rank[x] == rank[y]) ++rank[x];
    siz[x] += siz[y];
    par[y] = x;

    // x が y の親になるので、x と y の差分を diff_weight[y] に記録
    diff_weight[y] = w;
    return true;
  }
  Abel diff(int x, int y) { return weight(y) - weight(x); }
  int size(int x) { return siz[root(x)]; }
};

void Yes(bool b) {
  if (b)
    cout << "Yes" << endl;
  else
    cout << "No" << endl;
}
vector<long long> yaku(long long n) {
  vector<long long> ret;
  for (long long i = 1; i * i <= n; i++) {
    if (n % i == 0) {
      ret.push_back(i);
      if (i * i != n) ret.push_back(n / i);
    }
  }
  sort(ret.begin(), ret.end());  // 昇順に並べる
  return ret;
}
// #include <atcoder/lazysegtree>用
using S = long long;
using F = long long;

S op(S a, S b) { return std::max(a, b); }
S e() { return -INF; }
S mapping(F f, S x) { return f + x; }
F composition(F f, F g) { return f + g; }
F id() { return 0; }

priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> Q;
ll N, M, K, XP = 0;
vll cur;
vll A;
void dfs(ll now, ll past, vvll G) {
  A[now] = true;
  rep(i, G[now].size()) {
    if (G[now][i] != past && !A[G[now][i]]) {
      dfs(G[now][i], now, G);
    }
  }
  cur[now] = XP;
  XP++;
}
int GetRandom(int min, int max) {
  return min + (rand() * (max - min) / (RAND_MAX));
}

int main() {
  cout << fixed << setprecision(20);
  ll N, M, K, L, count;
  cin >> N >> M;
  count = Power(2, N, 998244353);
  modint998244353 ans = count;
  dsu d(N), d1(N);
  rep(i, M) {
    ll a, b, c;
    cin >> c;

    if (c == 1) {
      cin >> a >> b;
      --a, --b;
      if (d1.same(a, b) && a != b) ans = 0;
      d.merge(a, b);


      if(a!=b)ans /= 2;
      
    }
    else if (c == 2) {
      cin >> a >> b;
      --a, --b;
      if (d.same(a, b) || a == b) ans = 0;
      d1.merge(a, b);
      ans /= 2;
    } else {
      dsu x(N);
      d = x;
      d1 = x;
      ans = count;
    }
    cout << ans.val() << endl;
  }
}
0