結果
| 問題 |
No.2020 Sum of Common Prefix Length
|
| コンテスト | |
| ユーザー |
Nachia
|
| 提出日時 | 2022-07-22 21:48:55 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 183 ms / 2,000 ms |
| コード長 | 7,093 bytes |
| コンパイル時間 | 3,768 ms |
| コンパイル使用メモリ | 128,104 KB |
| 最終ジャッジ日時 | 2025-01-30 12:16:30 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 38 |
ソースコード
#include <vector>
#include <algorithm>
#include <iostream>
namespace nachia {
struct LinkCutTree {
struct S { unsigned int x; };
static S op(S l, S r) { return { l.x + r.x }; }
static S e() { return { 0 }; }
static void reverseprod(S& x) {}
struct F { };
static S mapping(F f, S x) { return x; }
static F composition(F f, F x) { return x; }
static F id() { return {}; }
struct Node {
Node* l = 0, * r = 0, * p = 0;
S a = e();
S prod = e();
F f = id();
// lazy & 1 : reverse
// lazy & 2 : deta
int lazy = 0;
void prepareDown() {
if(lazy & 2){
if(l) {
l->a = mapping(f, l->a);
l->prod = mapping(f, l->prod);
l->f = composition(f, l->f);
l->lazy |= 2;
}
if(r) {
r->a = mapping(f, r->a);
r->prod = mapping(f, r->prod);
r->f = composition(f, r->f);
r->lazy |= 2;
}
f = id();
}
if (lazy & 1) {
::std::swap(l, r);
if (l) { l->lazy ^= 1; reverseprod(l->prod); }
if (r) { r->lazy ^= 1; reverseprod(r->prod); }
}
lazy = 0;
}
void prepareUp() {
auto res = a;
if(l) res = op(l->prod, res);
if(r) res = op(res, r->prod);
prod = res;
}
Node** p_parentchild() {
if(!p) return nullptr;
if(p->l == this) return &p->l;
else if(p->r == this) return &p->r;
return nullptr;
}
void rotL() {
Node* t = p;
Node** parentchild_p = t->p_parentchild();
if(parentchild_p){ *parentchild_p = this; }
p = t->p;
t->p = this;
t->r = l;
if(l) l->p = t;
l = t;
}
void rotR() {
Node* t = p;
Node** parentchild_p = t->p_parentchild();
if(parentchild_p){ *parentchild_p = this; }
p = t->p;
t->p = this;
t->l = r;
if(r) r->p = t;
r = t;
}
};
::std::vector<Node> A;
LinkCutTree(int n = 0) {
A.resize(n);
}
LinkCutTree(const ::std::vector<S>& a) : LinkCutTree(a.size()) {
for (int i = 0; i < (int)a.size(); i++) A[i].prod = A[i].a = a[i];
}
Node* at(int idx) {
return &A[idx];
}
void splay(Node* c) {
c->prepareDown();
while(true) {
Node* p = c->p;
if(!p) break;
Node* pp = p->p;
if(pp) pp->prepareDown();
p->prepareDown();
c->prepareDown();
if(p->l == c){
if(!pp){ c->rotR(); }
else if(pp->l == p){ p->rotR(); c->rotR(); }
else if(pp->r == p){ c->rotR(); c->rotL(); }
else{ c->rotR(); }
}
else if(p->r == c){
if(!pp){ c->rotL(); }
else if(pp->r == p){ p->rotL(); c->rotL(); }
else if(pp->l == p){ c->rotL(); c->rotR(); }
else{ c->rotL(); }
}
else break;
if(pp) pp->prepareUp();
p->prepareUp();
}
c->prepareUp();
}
void expose(Node* c) {
auto p = c;
while(p){ splay(p); p = p->p; }
p = c;
while(p->p){ p->p->r = p; p = p->p; }
splay(c);
c->r = nullptr;
c->prod = (c->l ? op(c->l->prod, c->a) : c->a);
}
void evert(Node* c) {
expose(c);
c->lazy ^= 1;
reverseprod(c->prod);
c->prepareDown();
}
void link(Node* c, Node* r) {
if(c == r) return;
evert(c);
evert(r);
if(c->p) return;
c->p = r;
}
void cut(Node* c) {
expose(c);
if(!c->l) return;
c->l->p = nullptr;
c->l = nullptr;
}
// [u,v)
// post : evert(u) , splayLC(v)
Node* between(Node* u, Node* v) {
if(u == v) return nullptr;
evert(u);
expose(v);
v->l->prepareDown();
return v->l;
}
S prod(Node* s, Node* t) {
auto resv = between(s, t);
if(!resv) return t->a;
S res = resv->prod;
res = op(res, t->a);
return res;
}
S get(Node* p) {
expose(p);
return p->a;
}
void set(Node* p, S x) {
expose(p);
p->a = x;
p->prepareUp();
}
};
}
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <atcoder/modint>
using namespace std;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
#define rep(i,n) for(int i=0; i<(int)(n); i++)
const i64 INF = 1001001001001001001;
using modint = atcoder::static_modint<998244353>;
int N, Q;
vector<string> S;
int nx[410000][26];
vector<int> pos;
int NN;
int getNext(int p, char c){
int& dst = nx[p][c-'a'];
if(dst == -1) dst = NN++;
return dst;
}
int main(){
cin >> N;
S.resize(N);
rep(i,N) cin >> S[i];
nachia::LinkCutTree lct(410000);
cin >> Q;
int Z = Q + 1;
for(auto& s : S) Z += s.size();
rep(i,Z) rep(t,26) nx[i][t] = -1;
NN = 1;
pos.assign(N, 0);
rep(i,N) for(char c : S[i]){
int nx = getNext(pos[i], c);
if(nx == NN-1){
lct.link(lct.at(nx), lct.at(pos[i]));
}
pos[i] = nx;
lct.set(lct.at(pos[i]), { lct.get(lct.at(pos[i])).x + 1 });
}
rep(i,Q){
int t; cin >> t;
if(t == 1){
int x; cin >> x; x--;
char c; cin >> c;
int nx = getNext(pos[x], c);
if(nx == NN-1){
lct.link(lct.at(nx), lct.at(pos[x]));
}
pos[x] = nx;
lct.set(lct.at(pos[x]), { lct.get(lct.at(pos[x])).x + 1 });
}
if(t == 2){
int x; cin >> x; x--;
auto ans = lct.prod(lct.at(0), lct.at(pos[x])).x;
cout << ans << '\n';
}
}
return 0;
}
struct ios_do_not_sync{
ios_do_not_sync(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
}
} ios_do_not_sync_instance;
Nachia