第五天,也是講課的最後一天。數組
數據結構專題,講師:楊志燦數據結構
他的blog我彷佛找不到了……之前確定是在百度博客裏面。可是如今百度博客消失了。優化
PPT作的頗有感受,說了不少實用的技巧。ui
我以爲實際上是收穫最大的一天,由於聽懂了XDspa
中午划水code
下午的題也很是良心,然而@ghostfly233和@Melacau說他們作過原題???blog
問題就是很是卡常!n=10^5的nlogn題目,400組詢問,4秒?6億複雜度啊!排序
然而就是跑過了,我也沒辦法,樹狀數組複雜度不滿……遊戲
矩陣快速冪也卡……很是難受。get
【T1】
題意:有\(1\leq a\leq b\leq c\leq n\),問多少個\((a,b,c)\)三元組知足\(a+b^2\equiv c^3(mod\;k)\)。
題解:枚舉b,發現a+b^2的範圍是b^2+1到b^2+b是連續的一段,考慮計算這段中的c大於等於b的c^3的個數。
顯然用樹狀數組維護,複雜度有點問題,但是就是AC了XD。代碼很是的優美。
#include<cstdio> #include<cstring> int n,k,bit[100001]; long long ans; inline void I(int i){for(++i;i<=k;i+=i&-i)++bit[i];} inline int Q(int i){int s=0;for(++i;i;i-=i&-i)s+=bit[i];return s;} int main(){ freopen("exclaim.in","r",stdin); freopen("exclaim.out","w",stdout); int T; scanf("%d",&T); for(int t=1;t<=T;++t){ scanf("%d%d",&n,&k); ans=0; memset(bit,0,sizeof bit); int sum=0; for(int i=n;i;--i){ I(1ll*i*i*i%k); ++sum; long long l=1ll*i*i+1, r=1ll*i*i+i; ans+=1ll*(r/k-l/k)*sum+Q(r%k)-Q(l%k-1); } printf("Case %d: %lld\n",t,ans); } return 0; }
【T2】
題意:你玩一個多結局RPGgalgame(???),遊戲流程相似樹形結構,你總共通關了k次,每一個場景你都會得到該場景的價值(可能還有好感度和浪費手紙?),可是屢次經歷該場景就只有一次價值了。
價值都是正整數。
問他怎樣攻略能得到最大價值?
題解:有一個貪心思路:每次都走最大價值的路線,這樣必定最終價值也最大。
如何證實?
咱們先證實最大的必定要選吧,這樣後面的概括一下就完了。
先分類討論:
假設咱們沒有選擇最大的,那麼咱們從最大的這條路線往回回溯,遇到第一個有選取的場景,那麼走這個場景的這條(任意一條)路線,均可以換成走最大的路線。
爲何?假設走到這個場景的路線只有一條,那麼顯然更優,由於前面的價值都同樣,換成這條會更優。
假設有多條,那麼其中任意一條換掉以後,多了最優的這一條的價值收益,而且本身這條的收益還不用徹底減掉,由於還有其餘的路線走過,因此比上一種狀況還來得優。
那麼咱們就證實了,最大的路線必定要選,接下來把最大的路線的收益刪去,變成0,那麼這時再選取最大的仍是同樣的。因而證實完畢。
那麼如何處理呢?包括查詢最大收益和修改。
其實這就是一個線段樹可以維護的:
把節點按照DFS序排序,一個點的全部孩子就是一段區間。
把全部的葉子節點(結局)按照DFS序扔進線段樹,初始值就是路線收益,查詢時直接查最大值,修改時,咱們知道一個點的孩子對應一段區間,因此區間減法便可。
查詢k次,每次O(1),修改最多n次,每次O(log 葉子節點數)。
那麼這題就算作完了。
#include<cstdio> #include<algorithm> using namespace std; int n,k,a[200001],fa[200001],t[200001],cnt; int h[200001],to[200001],nxt[200001],tot; inline void ins(int x,int y){nxt[++tot]=h[x];to[tot]=y;h[x]=tot;} int L[200001],R[200001],vis[200001]; long long dat[524289],lazy[524289],ans; int pos[524289]; void dfs(int u){ if(!h[u]) {L[u]=R[u]=++cnt, t[cnt]=u; return;} L[u]=n; for(int i=h[u];i;i=nxt[i]) dfs(to[i]), L[u]=min(L[u],L[to[i]]), R[u]=max(R[u],R[to[i]]); } inline void pushdown(int i){ lazy[i<<1]+=lazy[i]; lazy[i<<1|1]+=lazy[i]; dat[i<<1]+=lazy[i]; dat[i<<1|1]+=lazy[i]; lazy[i]=0; } void build(int i,int l,int r){ pos[i]=l; if(l==r) return; int mid=l+r>>1; build(i<<1,l,mid), build(i<<1|1,mid+1,r); } void Ins(int i,int l,int r,int a,int b,int v){ if(a<=l&&r<=b) {dat[i]+=v; lazy[i]+=v; return;} if(r<a||b<l) return; pushdown(i); int mid=l+r>>1; Ins(i<<1,l,mid,a,b,v); Ins(i<<1|1,mid+1,r,a,b,v); dat[i]=max(dat[i<<1],dat[i<<1|1]); pos[i]=dat[i<<1]>=dat[i<<1|1]?pos[i<<1]:pos[i<<1|1]; } int main(){ freopen("game.in","r",stdin); freopen("game.out","w",stdout); scanf("%d%d",&n,&k); k=min(k,n); for(int i=1;i<=n;++i) scanf("%d",a+i); for(int i=1,x,y;i<n;++i) scanf("%d%d",&x,&y), ins(x,y), fa[y]=x; dfs(1); build(1,1,cnt); for(int i=1;i<=n;++i) Ins(1,1,cnt,L[i],R[i],a[i]); for(int i=1;i<=k;++i){ int p=t[pos[1]]; ans+=dat[1]; int sum=0; while(p&&!vis[p]) Ins(1,1,cnt,L[p],R[p],-a[p]), vis[p]=1, sum+=a[p], p=fa[p]; } printf("%lld",ans); return 0; }
【T3】
題意:求有向圖中長度小於k的環的個數,沒有自環。
題解:簡單矩陣,有著名定理支持:鄰接矩陣的k次方就是從一個節點出發,通過k步到達另外一個節點的路徑數。
即求\(A^1+A^2+\cdots+A^{k-1}\)。
簡單矩陣快速冪便可,加一個稀疏矩陣優化,跑的飛快。根本不須要分治。
#include<cstdio> #include<cstring> int n,n2,k,p,ans; struct Mat{int fk[200][200];}M1,M2; inline Mat operator*(Mat p1,Mat p2){ Mat p3;memset(p3.fk,0,sizeof p3.fk); for(register int i=0;i<n2;++i) for(register int k=0;k<n2;++k) if(p1.fk[i][k]) for(register int j=0;j<n2;++j) p3.fk[i][j]=(p3.fk[i][j]+1ll*p1.fk[i][k]*p2.fk[k][j])%p; return p3; } int main(){ freopen("tour.in","r",stdin); freopen("tour.out","w",stdout); scanf("%d",&n); n2=n<<1; char ch; for(register int i=0;i<n;++i) M1.fk[i][i]=M2.fk[i][i]=M2.fk[i+n][i+n]=1; for(register int i=n;i<n2;++i) for(register int j=0;j<n;++j) (ch=getchar())=='Y'?M1.fk[i][j]=M1.fk[i][j+n]=1:(ch!='N'?--j:0); scanf("%d%d",&k,&p); --k; if(p==1){puts("0");return 0;} while(k){ if(k&1) M2=M2*M1; k>>=1; M1=M1*M1; } for(register int i=0;i<n;++i) ans=(ans+M2.fk[i+n][i])%p; printf("%d",ans); return 0; }