不知道爲啥當時咕了,然後咕了太久了,回來寫反思的時候已經沒有反思了。
反正我好菜啊,直接寫題解吧。
T1:數據結構
大意:維護序列,單點修改,查詢某個區間$[l,r]$的區間和的歷史最小值。$n,q \le 10^5$
$KD-tree$又日爆一切二維幾何了。
牛神又日爆一切$KD-tree$題了。
矩形加,歷史最小值,簡單維護。$O(q\sqrt{n})$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define S 400005 4 #define ll long long 5 int cmp,op[S],x[S],y[S],n,m,a[S],qc,mxl[S],mnr[S],mxr[S],mnl[S]; 6 ll w[S],lz[S],mnlz[S],pre[S],mn[S]; 7 struct P{int l,r;}Q[S],T[S]; 8 ll cal(P x){return cmp?1000000000ll*x.l+x.r:1000000000ll*x.r+x.l;} 9 bool operator<(P x,P y){return cal(x)<cal(y);} 10 #define lc p<<1 11 #define rc lc|1 12 #define fa p>>1 13 void build(int p,int l,int r){ 14 if(l>r)return; 15 cmp^=1; int md=l+r>>1; 16 nth_element(Q+l,Q+md,Q+r+1); 17 T[p]=Q[md];mn[p]=w[p]=pre[mxr[p]=mnr[p]=T[p].r]-pre[(mnl[p]=mxl[p]=T[p].l)-1]; 18 build(lc,l,md-1);build(rc,md+1,r);cmp^=1; 19 mnr[fa]=min(mnr[fa],mnr[p]); mxl[fa]=max(mxl[fa],mxl[p]); 20 mxr[fa]=max(mxr[fa],mxr[p]); mnl[fa]=min(mnl[fa],mnl[p]); 21 } 22 void down(int p){ 23 if(!lz[p]&&!mnlz[p])return; 24 mn[lc]=min(mn[lc],w[lc]+mnlz[p]);mn[rc]=min(mn[rc],w[rc]+mnlz[p]); 25 w[lc]+=lz[p];w[rc]+=lz[p]; 26 mnlz[lc]=min(mnlz[lc],lz[lc]+mnlz[p]);mnlz[rc]=min(mnlz[rc],lz[rc]+mnlz[p]); 27 lz[lc]+=lz[p];lz[rc]+=lz[p]; 28 lz[p]=mnlz[p]=0; 29 } 30 void add(int L,int v,int p){ 31 if(mxr[p]<L||mnl[p]>L)return; 32 if(mxl[p]<=L&&mnr[p]>=L){lz[p]+=v;mnlz[p]=min(mnlz[p],lz[p]);w[p]+=v;mn[p]=min(mn[p],w[p]);return;} 33 if(T[p].l<=L&&T[p].r>=L)w[p]+=v,mn[p]=min(mn[p],w[p]); 34 down(p);add(L,v,lc);add(L,v,rc); 35 } 36 ll ask(int l,int r,int p){ 37 if(T[p].l==l&&T[p].r==r)return mn[p]; 38 cmp^=1;down(p);return ask(l,r,cal((P){l,r})<cal(T[p])?lc:rc); 39 } 40 int main(){ 41 scanf("%d%d",&n,&m); 42 for(int i=1;i<=n;++i)scanf("%d",&a[i]),pre[i]=pre[i-1]+a[i]; 43 for(int i=1;i<=m;++i){ 44 scanf("%d%d%d",&op[i],&x[i],&y[i]); 45 if(op[i]==2)Q[++qc]=(P){x[i],y[i]}; 46 } 47 build(1,1,qc); 48 for(int i=1;i<=m;++i) 49 if(op[i]==2)cmp=0,printf("%lld\n",ask(x[i],y[i],1)); 50 else add(x[i],y[i]-a[x[i]],1),a[x[i]]=y[i]; 51 }
T2:B
大意:給定$01$串$S,T$,$S_i=[ai+b \le c (\mod n)]$。$S$是循環的。求$S$從第$p$位開始能和$T$匹配幾位,或者單點修改$T$。$|T| \le 10^5,others \le 10^9$
如果$T_i=0$那麼我們要查的就是$[0 \le a(i+p)+b \le c (\mod n)]$,也就是說$[-ap \le ai+b \le c-ap (\mod n)]$
所以只與$ai+b$有關在最開始的時候插入樹狀數組然後查詢的時候只與$p$有關查詢上述區間即可。
$T_i=1$同理。修改的話只要在樹狀數組裏一刪一加就行了。
1 #include<cstdio> 2 #define S 6000007 3 int n,m,b,c,q;char t[S];long long a; 4 struct hash_map{ 5 int fir[S],l[S],to[S],v[S],ec; 6 int&operator[](int x){ int r=x%S; 7 for(int i=fir[r];i;i=l[i])if(to[i]==x)return v[i]; 8 l[++ec]=fir[r];fir[r]=ec;to[ec]=x;return v[ec]; 9 } 10 }; 11 struct Fenwick_Tree{ 12 hash_map t; 13 void add(int p,int v=1){for(;p<=n;p+=p&-p)t[p]+=v;} 14 int ask(int p,int a=0){for(;p;p^=p&-p)a+=t[p];return a;} 15 int query(int l,int r){return l<=r?ask(r)-ask(l-1):ask(n)-(ask(l-1)-ask(r));} 16 }T[2]; 17 int mo(long long x){return (x%n+n)%n+1;} 18 int main(){ 19 scanf("%d%lld%d%d%d%s%d",&n,&a,&b,&c,&m,t,&q); 20 for(int i=0;i<m;++i)t[i]-=48,T[t[i]].add(mo(a*i)); 21 for(int _=1,o,p;_<=q;++_){ 22 scanf("%d%d",&o,&p); 23 if(o==2)T[t[p]].add(mo(a*p),-1),T[t[p]^=1].add(mo(a*p)); 24 else printf("%d\n",T[0].query(mo(-a*p-b+c),mo(-a*p-b-1))+T[1].query(mo(-a*p-b),mo(-a*p-b+c-1))); 25 } 26 }
T3:C
大意:樹,隨機點出發,每個點有一個$01$狀態,每一次會隨機選擇一個點,沿樹邊走到那個點並將其權值取反。所有點權值都相同時結束。求期望經過的總距離。$n \le 10^5$
期望線性性,對每個點考慮貢獻。
這是完全隨機的遊走,從每個點出發走到的點的距離期望是確定的可以直接換根$dp$得到。
然後所有點之間的區別就只剩下了:當前權值。狀態的差異還有樹上有幾個權值爲$1$的點。
根據這個設出$dp$。
這個東西,首先狀態定義是:走到當前點,遊戲未結束,此時當前點被經過的期望次數。要時刻注意你考慮的是一個點而不是一種權值的貢獻
兩個轉移是出邊和。前面的那個$\frac{1}{n}$的常量是分別跟着後面係數爲$\frac{1}{n}$
分別討論選中的是當前點,還是權值爲$01$的點(第一個不包含於後兩個)
所謂的邊界情況是,$val_{0,0}=val_{0,1}=val_{n,0}=val{n,1}=0$。
然後$val_{n-1,0}$選自己會轉移到$val_{n,1}$,不滿足含義中“遊戲仍在繼續”的限制,所以沒有$\frac{1}{n}$的係數。$val_{1,1}$同理。
至此我們考慮了遊戲仍在繼續的情況(遊戲不再繼續你自然就不會再走)。沒有考慮的就是隨機出發所走的第一步,所以所有點的期望經過次數還要加$\frac{1}{n}$
然後並不需要根據方程在$i=n-1$處列額外的方程,這東西有明顯的對稱性,所以顯然有$val_{n-1,0}=val_{1,1},val_{n-1,1}=val_{1,0}$。
所以就解方程就行了。爆寫式子有點細節。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int S=1e5+5,mod=1e9+7; 4 int fir[S],l[S],to[S],ec,n,d[S],sz[S],inv[S],v11,v10,cnt,ans;char s[S]; 5 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;} 6 int mo(int x){return x>=mod?x-mod:x;} 7 void dfs(int p){sz[p]=1;for(int i=fir[p],y;y=to[i];i=l[i])dfs(y),sz[p]+=sz[y],d[p]=mo(d[p]+mo(d[y]+sz[y]));} 8 void DFS(int p){for(int i=fir[p],y;y=to[i];i=l[i])d[y]=(0ll+d[p]-sz[y]+n-sz[y]+mod)%mod,DFS(y);} 9 int qp(int b,int t=mod-2,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;} 10 int gcd(int a,int b){return b?gcd(b,a%b):a;} 11 struct coef{ 12 int c0,c1,c; 13 coef operator+(coef x){return (coef){mo(c0+x.c0),mo(c1+x.c1),mo(c+x.c)};} 14 coef operator-(coef x){return (coef){mo(c0+mod-x.c0),mo(c1+mod-x.c1),mo(c+mod-x.c)};} 15 coef operator*(long long x){return (coef){c0*x%mod,c1*x%mod,c*x%mod};} 16 coef operator-(int x){return (coef){c0,c1,mo(c+mod-x)};} 17 int cal(){return (1ll*c0*v10+1ll*c1*v11+c)%mod;} 18 }c[S][2]; 19 int main(){ 20 scanf("%d%s",&n,s+1); inv[1]=1; 21 for(int i=2;i<=n;++i)inv[i]=mod-mod/i*1ll*inv[mod%i]%mod; 22 for(int i=2,a;i<=n;++i)scanf("%d",&a),link(a,i); 23 dfs(1);DFS(1); 24 c[1][0].c0=c[1][1].c1=1; 25 for(int i=1;i<n-1;++i) 26 c[i+1][1]=(c[i][1]*n-c[i-1][1]*(i-1)-c[i-1][0]-(i!=1))*inv[n-i], 27 c[i+1][0]=(c[i][0]*n-c[i-1][0]*i-c[i+1][1]-1)*inv[n-i-1]; 28 c[n][0]=c[1][1]-c[n-1][0]; 29 c[n][1]=c[1][0]-c[n-1][1]; 30 if(!c[n][1].c0)swap(c[n][0],c[n][1]);else c[n][0]=c[n][0]*qp(c[n][0].c0)*c[n][1].c0-c[n][1]; 31 v11=mod-1ll*qp(c[n][0].c1)*c[n][0].c%mod,v10=mo(mod+mod-1ll*v11*c[n][1].c1%mod-c[n][1].c)*1ll*qp(c[n][1].c0)%mod,cnt=0,ans=0; 32 for(int i=1;i<=n;++i)cnt+=s[i]-48; 33 for(int i=1;i<=n;++i)ans=(ans+(c[cnt][s[i]-48].cal()+inv[n])*1ll*d[i])%mod; 34 printf("%lld\n",ans*1ll*qp(n)%mod); 35 }