1. 程式人生 > >[JZOJ5915]【NOIP2018模擬10.19】明日之星

[JZOJ5915]【NOIP2018模擬10.19】明日之星

Description

給定一棵樹,每個節點有一個權值ai和一個字串si
q組詢問,每次詢問一個字串S和兩個節點x,y
求x到y路徑上每個節點的字串在S中出現的次數乘上各自的權值總和。
有單點修改權值的操作。
n,q<=200000,si,S400000\sum si,\sum S\leq 400000
強制線上

Solution

首先對於樹上路徑的問題,並且只是加和減,我們可以考慮括號序。
對於每個節點進入的時候打一個1的標記,出的時候打一個-1的標記

那麼一條路徑xtoyx\ to\ y,令p=lca(x,y)p=lca(x,y),那麼這條路徑可以表示為兩個區間和[

in[p],in[x]],(in[p],in[y]]\left[in[p],in[x]\right],\left(in[p],in[y]\right]

這樣就將樹上問題轉化成了序列問題。

對於這個括號序,我們建一個線段樹,線段樹上的每個區間建AC自動機
這樣總的AC自動機大小是2nlogn2n\log n

我們還要支援修改權值,那麼在AC自動機fail樹上修改鏈,相當於子樹修改,直接用樹狀陣列維護fail樹的DFS序即可。

總的複雜度O(nlog2n)O(n\log^2 n)
出題人還卡了空間
程式碼及其噁心(出題人已被群毆,不省人事…)

Code

#pragma GCC optimize(2)
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define N 200005
#define M 800005
#define
L 8000005
using namespace std; int n1,n,m,m1,tp,a1[N][2],t[M][2],pr[N],fs[N],da[M],len,dep[M],n3; int nt[2*N],dt[2*N],f[N][20]; int t1[L][5],wz[22][M],fi[L],nx[L],d1[L],dfn[L],d[L],fail[L],sz[L],c[L]; int m2,n2,in[N],out[N],rt[M],de[M],c1[26]; char st[M],ch[M]; void link(int x,int y) { nt[++m1]=fs[x]; dt[fs[x]=m1]=y; } void read(int &x) { x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); } void lk(int x,int y) { nx[++m2]=fi[x]; d1[fi[x]=m2]=y; } void dfs(int k,int fa) { dep[k]=dep[fa]+1; f[k][0]=fa; da[in[k]=++da[0]]=k; for(int i=fs[k];i;i=nt[i]) { int p=dt[i]; if(p!=fa) dfs(p,k); } da[out[k]=++da[0]]=k; } int lca(int x,int y) { if(dep[x]>dep[y]) swap(x,y); for(int l=dep[y]-dep[x],j=0;l;l>>=1,j++) if(l&1) y=f[y][j]; for(int j=17;x!=y;) { while(j&&f[x][j]==f[y][j]) j--; x=f[x][j],y=f[y][j]; } return x; } void dg(int k) { dfn[k]=++dfn[0]; sz[k]=1; for(int i=fi[k];i;i=nx[i]) dg(d1[i]),sz[k]+=sz[d1[i]]; } int lowbit(const int &k) { return k&(-k); } void put(int k,const int &v) { while(k<=n3) c[k]+=v,k+=lowbit(k); } int get(int k) { int s=0; while(k) s+=c[k],k-=lowbit(k); return s; } void change(int l,int r,int v) { put(l,v),put(r+1,-v); } void make(int k2,int l,int r) { int k1=rt[k2]; fo(i1,l,r) { int k=k1,i=da[i1]; fo(j,a1[i][0],a1[i][1]) { int c=c1[st[j]-'A']; if(!t1[k][c]) t1[k][c]=++n2; k=t1[k][c]; } wz[de[k2]][i1]=k; } int x=0,y=1; d[1]=k1; while(x<y) { int k=d[++x]; fo(c,0,4) { if(t1[k][c]) { d[++y]=t1[k][c]; int p=fail[k]; while(p&&!t1[p][c]) p=fail[p]; if(!p) fail[d[y]]=k1; else fail[d[y]]=t1[p][c]; lk(fail[d[y]],d[y]); } } } dg(k1); fo(i1,l,r) { int i=da[i1],i2=wz[de[k2]][i1]; if(i1==in[i]) change(dfn[i2],dfn[i2]+sz[i2]-1,pr[i]); else change(dfn[i2],dfn[i2]+sz[i2]-1,-pr[i]); } } void build(int k,int l,int r) { rt[k]=++n2; make(k,l,r); if(l==r) return; int mid=(l+r)>>1; t[k][0]=++n1,de[n1]=de[k]+1,build(t[k][0],l,mid); t[k][1]=++n1,de[n1]=de[k]+1,build(t[k][1],mid+1,r); } int gs(int k) { int s=0; fo(i,1,len) { int c=c1[ch[i]-'A']; while(fail[k]&&!t1[k][c]) k=fail[k]; if(t1[k][c]) k=t1[k][c]; s+=get(dfn[k]); } return s; } int query(int k,int l,int r,int x,int y) { if(x>y||!k||y<l||x>r) return 0; if(x<=l&&r<=y) return gs(rt[k]); int mid=(l+r)>>1; return query(t[k][0],l,mid,x,y)+query(t[k][1],mid+1,r,x,y); } void ins(int k,int l,int r,int w,int y) { change(dfn[wz[de[k]][w]],dfn[wz[de[k]][w]]+sz[wz[de[k]][w]]-1,y); if(l==r) return; int mid=(l+r)>>1; if(w<=mid) ins(t[k][0],l,mid,w,y); else ins(t[k][1],mid+1,r,w,y); } int main() { cin>>n>>tp; int le=0; bool pd=1; fo(i,1,n) { scanf("\n%s",ch+1); int l1=strlen(ch+1); a1[i][0]=le+1; fo(j,1,l1) st[++le]=ch[j]; a1[i][1]=le; } fo(i,1,n) read(pr[i]); fo(i,1,n-1) { int x,y; if(x>y) swap(x,y); read(x),read(y); if(x!=y-1) pd=0; link(x,y),link(y,x); } c1[0]=0; c1[2]=1; c1['G'-'A']=2; c1['T'-'A']=3; c1['U'-'A']=4; dfs(1,0); fo(j,1,18) fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1]; n1=1; n3=n*27; build(1,1,2*n); int q,ans=0; cin>>q; le=0; fo(i,1,q) { int ip,x,y; read(ip),read(x),read(y); x^=(ans*tp),y^=(ans*tp); if(ip==1) { scanf("%s",ch+1); len=strlen(ch+1); int lp=lca(x,y); ans=query(1,1,2*n,in[lp],in[x])+query(1,1,2

相關推薦

[JZOJ5915]NOIP2018模擬10.19明日

Description 給定一棵樹,每個節點有一個權值ai和一個字串si q組詢問,每次詢問一個字串S和兩個節點x,y 求x到y路徑上每個節點的字串在S中出現的次數乘上各自的權值總和。 有單點修改權值的操作。 n,q<=200000,∑si,∑S≤4000

JZOJ5914. NOIP2018模擬10.19盟主的憂慮

Description 江湖由 N 個門派(2≤N≤100,000,編號從 1 到 N)組成,這些門派之間有 N-1 條小道將他們連線起來,每條道路都以“尺”為單位去計量,武林盟主發現任何兩個門派都能夠直接或者間接通過小道連線。 雖然整個江湖是可以互相到達的,但是他擔心有心懷不軌之徒破壞

jzoj5913. NOIP2018模擬10.19林下風氣(樹形dp)

5913. 【NOIP2018模擬10.19】林下風氣 Description 裡口福因有林下風氣,帶領全國各地高校掀起了一股AK風,大家都十分痴迷於AK。裡口福為了打擊大家的自信心,出了一道自以為十分困難的題目。 裡口福有一棵樹,第i個節點上有點權ai,他的問

JZOJ5932. NOIP2018模擬10.27情報中心

傳送門 preface   這道題資料超級水,暴力70。正解也超級玄學,需要各種卡常技巧。 分析   首先看資料範圍,貌似O(k)才能過廢話。既然是要O(k)的出答案,那就只能預處理了。   設f[i][j][k]表示以第i好結點為起點,在最短距離不超過j的情況下,是否能到達k號結點。對於這樣的東西

jzoj5938. NOIP2018模擬10.30分離計劃(二分)

5938. 【NOIP2018模擬10.30】分離計劃 Description 眾所周知,小Z擁有者足以毀滅世界的力量,可惜他不能控制這份力量,小J和小Z的關係十分親密,一天小J預感到了小Z體內的力量將要爆發。 這次爆發的力量比以往都要強大,以至於將小Z分為了兩個整體,彼此之間靠著萬

jzoj5935. NOIP2018模擬10.29小凱學數學(區間dp)

5935. 【NOIP2018模擬10.29】小凱學數學 Description 由於小凱上次在找零問題上的疑惑,給大家在考場上帶來了很大的麻煩,他決心好好學習數學 本次他挑選了位運算專題進行研究 他發明了一種叫做“小凱運算”的運算子: a$b =( (a&b) + (a|b

jzo5934. NOIP2018模擬10.29列隊(二分圖匹配)

5934. 【NOIP2018模擬10.29】列隊 Description Sylvia是一個熱愛學習的女孩子。 在平時的練習中,他總是能考到std以上的成績,前段時間,他參加了一場練習賽,眾所周知,機房是一個 的方陣。這天,他又打爆了std,感到十分無聊,便想要hack機房內同學的

jzoj5922. NOIP2018模擬10.23sequence(組合數)

5922. 【NOIP2018模擬10.23】sequence Description 小 F 是一位 Hack 國的居民,他生活在一條長度為 n 的街道上,這個街道上總共有 n 個商店。每個商店裡售賣著不同的 Hack 技能包,每個商店本身也會有個便利值。初始時,每個商店的便利值均

jzoj5920. NOIP2018模擬10.21風箏(dp,最長上升子序列)

5920. 【NOIP2018模擬10.21】風箏 Description 當一陣風吹來,風箏飛上天空,為了你,而祈禱,而祝福,而感動…… Description oyiya 在 AK 了 IOI 之後來到了鄉下,在田野中玩耍,放鬆身心。 他發現前面有一排小朋

jzoj5919. NOIP2018模擬10.22逛公園(tarjan,二分)

5919. 【NOIP2018模擬10.22】逛公園 Description 琥珀色黃昏像糖在很美的遠方,思念跟影子在傍晚一起被拉長…… Description 小 B 帶著 GF 去逛公園,公園一共有 n 個景點,標號為 1 . . . n。景點之間有 m

JZOJ 5937. NOIP2018模擬10.30斬殺計劃

問題 小G有n個小弟,第i個小弟有ai點攻擊力,小G有m點血量。 小J在小G找小第的時間裡去找小Z學到了膜法,他在大戰前配置了三種魔法藥水 1:複用型藥水:花費1法力值,選擇小G的攻擊力小於等於2的一個小弟讓他跟隨自己(變為自己的小弟並且攻擊力和屬於小G時一樣

JZOJ 5936. NOIP2018模擬10.29逛公園

題目 解題思路 50分可以直接暴力。 能用一個變數儲存的,絕對不允許用陣列!! 定址時間卡爆!!! # d

JZOJ 5931. NOIP2018模擬10.27氣泡排序

題目 求一個n的全排列的變成 1…n的序列 期望最少交換次數。 題解 實在想不出來,可以找規律。 其實這題不需要找規律。 方法1 第一類斯特林數靈感? hzj的第一題,序列前n-1個元素只能夠與第n個交換,想到一圈一圈地換。 這裡也是類似的,只不過任意兩個元素都可以交

JZOJ 5932. NOIP2018模擬10.27情報中心

題目 給定一個點數為n個圖,m條邊。 走一條邊算1步。 共有q個詢問 每個詢問中有k個點,求有多少個點可以走最多v步走到詢問中的任意一個點。 資料範圍 n

JZOJ 5933. NOIP2018模擬10.27百鴿籠

題目 鴿鴿鴿 有一個序列,有3種操作。 ①刪除最左邊的元素 ②在序列的最左邊加入一個數。 ③查詢序列中第l個數到第r個數中第k小的數。 題解 想到之前ifk通過動態樹最終狀態的dfs序將問題轉化成靜態樹問題,我打算也用類似的方法。 其實不需要。 每次刪除和插入的都是最左邊的

JZOJ 5925. NOIP2018模擬10.25naive 的瓶子

題目 有 n 個瓶子,它們在桌子上排成一排。第 i 個瓶子的顏色為 ci,每次操作可以選擇兩個相鄰的瓶子,消耗他們顏色的數值乘積的代價將其中一個瓶子的顏色變成另一個瓶子的顏色。 現在要讓所以瓶子的顏色都一樣,操作次數不限,但要使得操作的總代價最小。 題解 比賽時看錯題了,看成

5928. NOIP2018模擬10.26蘋果

題目 對區間 [ 1 ,

JZOJ 5926. NOIP2018模擬10.25naive 的圖

題目 給定一個帶權無向圖。每個點都有它的顏色。定義 D ( s