【LOJ】#2046. 「CQOI2016」路由表
阿新 • • 發佈:2018-08-18
end || ++ out max using etc template 查詢
題解
題面太長無法閱讀系列……
這裏說的選擇改變指的是在下面區間裏碰上了一個更長的可匹配的地址,如果可匹配但是匹配長度沒有當前的值大,那麽不算改變
我們建一個可持久化的trie,查詢的時候先在前\(a - 1\)個裏找到最長的可以得到的地址
然後再在區間的trie裏找到那條鏈上,如果碰到一個結束點且比我們初始長度大的路徑串,就丟進一個棧裏,維護棧的遞增
最後棧的長度就是答案
代碼
#include <bits/stdc++.h> #define enter putchar(‘\n‘) #define space putchar(‘ ‘) #define pii pair<int,int> #define fi first #define se second #define MAXN 1000005 #define pb push_back #define mp make_pair #define eps 1e-8 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) f = -1; c = getchar(); } while(c >= ‘0‘ && c <= ‘9‘) { res = res * 10 + c - ‘0‘; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar(‘-‘);} if(x >= 10) out(x / 10); putchar(‘0‘ + x % 10); } int M; char s[35]; struct node { int son[2],siz,ed; }tr[MAXN * 32]; int Ncnt,rt[MAXN],cnt; int sta[MAXN],top; void Insert(int v,int l) { rt[++cnt] = ++Ncnt; int *y = &rt[cnt],x = rt[cnt - 1]; tr[*y] = tr[x]; for(int i = 31 ; i >= 31 - l + 1 ; i--) { int c = (v >> i) & 1; y = &tr[*y].son[c];x = tr[x].son[c]; *y = ++Ncnt; tr[*y] = tr[x]; tr[*y].siz++; } if(!tr[*y].ed) tr[*y].ed = cnt; } int Get_MaxL(int a,int v) { int p = rt[a]; int res = 0; for(int i = 31 ; i >= 0 ; --i) { int c = (v >> i) & 1; if(tr[p].son[c]) p = tr[p].son[c]; else break; if(tr[p].ed) res = max(res,31 - i + 1); } return res; } int Query(int L,int R,int v,int len) { top = 0; --L; int x = rt[L],y = rt[R]; for(int i = 31 ; i >= 0 ; --i) { int c = (v >> i) & 1; if(tr[tr[y].son[c]].siz - tr[tr[x].son[c]].siz) { y = tr[y].son[c];x = tr[x].son[c]; } else break; if(tr[y].ed && 31 - i + 1 > len) { while(top && sta[top] > tr[y].ed) --top; sta[++top] = tr[y].ed; } } return top; } void Solve() { read(M); int a,b; while(M--) { scanf("%s",s + 1); if(s[1] == ‘A‘) { scanf("%s",s + 1); int L = strlen(s + 1); int v = 0,now = 0; for(int i = 1 ; i <= L ; ++i) { if(s[i] == ‘.‘ || s[i] == ‘/‘) { v = v << 8 | now; now = 0; } else now = now * 10 + s[i] - ‘0‘; } Insert(v,now); } else { scanf("%s",s + 1); int L = strlen(s + 1); int v = 0,now = 0; for(int i = 1 ; i <= L ; ++i) { if(s[i] == ‘.‘) { v = v << 8 | now; now = 0; } else now = now * 10 + s[i] - ‘0‘; } v = v << 8 | now; read(a);read(b); L = Get_MaxL(a - 1,v); out(Query(a,b,v,L));enter; } } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
【LOJ】#2046. 「CQOI2016」路由表