省选前作业题汇总4

RT

Part1

BZOJ 5125 小Q的书架

决策单调性优化DP,设$dp[i][j]$表示前$i$个数分成$j$段的最小代价,转移是$dp[i][j]=min(dp[i][j],dp[k][j-1]+rev(k+1,i))$,暴力移动指针求区间逆序对。因为后面那坨东西并不是单峰的所以用分治解决

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=40005,inf=2e9;
 6 int a[N],b[N],dp[N],tmp[N];
 7 int n,m,lp,rp,ans;
 8 void Add(int x,int y)
 9 {
10     while(x<=n)  
11         b[x]+=y,x+=x&-x;
12 }
13 int Query(int x)
14 {
15     int ret=0;
16     while(x)
17         ret+=b[x],x-=x&-x;
18     return ret;
19 }
20 void Move(int l,int r)
21 {
22     while(lp<l) Add(a[lp],-1),ans-=Query(a[lp++]-1);
23     while(lp>l) Add(a[--lp],1),ans+=Query(a[lp]-1);
24     while(rp>r) Add(a[rp],-1),ans-=rp-lp-Query(a[rp]),rp--;
25     while(rp<r) Add(a[++rp],1),ans+=rp-lp+1-Query(a[rp]);
26 }
27 void Solve(int l,int r,int ll,int rr)
28 {
29     if(l>r) return;
30     int mid=(l+r)>>1,mini=inf,pts=ll;
31     for(int i=ll;i<=min(rr,mid-1);i++)
32     {
33         Move(i+1,mid);
34         if(dp[i]+ans<mini)
35             mini=dp[i]+ans,pts=i;
36     }
37     tmp[mid]=mini;
38     Solve(l,mid-1,ll,pts);
39     Solve(mid+1,r,pts,rr);
40 }
41 int main()
42 {
43     scanf("%d%d",&n,&m),lp=1,rp=0;
44     for(int i=1;i<=n;i++)
45         scanf("%d",&a[i]);
46     for(int i=1;i<=n;i++)
47         Move(1,i),dp[i]=ans;    
48     for(int i=2;i<=m;i++)
49     {
50         Solve(1,n,1,n);
51         for(int j=1;j<=n;j++) dp[j]=tmp[j];
52     }
53     printf("%d",dp[n]);
54     return 0;
55 }
56 
View Code

BZOJ 2554 Color

orz liu_runda

求若干数量的球成为答案的期望和某种颜色的球成为答案的概率

主要是学一学形如$f[i]=p*f[i-1]+q*f[i+1]$这种东西怎么做:要求两边能搞出来,从一边开始带着推,推导另一边得解,最后再倒着代回来

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=10005;
 6 char str[N]; int cnt[N];
 7 double ans,tr[N],dp[N],k[N],b[N];
 8 int main()
 9 {
10     scanf("%s",str+1);
11     int n=strlen(str+1);
12     for(int i=1;i<=n;i++)
13         cnt[str[i]-'A']++;
14     for(int i=1;i<n;i++)
15         tr[i]=1.0*n*(n-1)/2/i/(n-i);
16     dp[n]=0,k[1]=1,b[1]=tr[1];
17     for(int i=2;i<n;i++)
18     {
19          b[i]=b[i-1]*(i-1)/i/2+tr[i];
20          k[i]=1.0*(i+1)/i/2;
21          k[i]=k[i]/(1-k[i-1]*(i-1)/i/2);
22          b[i]=b[i]/(1-k[i-1]*(i-1)/i/2);
23     }
24     for(int i=n-1;i;i--)
25         dp[i]=dp[i+1]*k[i]+b[i];
26     for(int i=0;i<=25;i++)
27         ans+=dp[cnt[i]]*cnt[i]/n;
28     printf("%.1f",ans);
29     return 0;
30 }
View Code

CF434E Furukawa Nagisa's Tree

题很好 咕咕咕(yda 咕的Blog

CF666C Codeword

发现答案和序列具体长什么样没有什么关系,我们只关心序列长度,于是递推

 1 #include<map>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define vint vector<int> 
 7 using namespace std;
 8 const int N=100005,mod=1e9+7;
 9 int T,op,rd,fac[N],inv[N],pw1[N],pw2[N],iv1[N];
10 char str[N]; map<int,vint> mp;
11 
12 template<class Type> void exGCD(Type a,Type b,Type &x,Type &y)
13 {
14     if(!b) {x=1,y=0; return;}
15     else exGCD(b,a%b,y,x),y-=a/b*x;
16 }
17 
18 int Inv(int x)
19 {
20     int xx,yy;
21     exGCD(x,mod,xx,yy);
22     return (xx%mod+mod)%mod;
23 }
24 void Pre(int Maxx)
25 {
26     fac[0]=inv[0]=pw1[0]=pw2[0]=iv1[0]=1;
27     for(int i=1;i<=Maxx;i++) fac[i]=1ll*fac[i-1]*i%mod;
28     inv[Maxx]=Inv(fac[Maxx]);
29     for(int i=Maxx-1;i;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
30     for(int i=1;i<=Maxx;i++) pw1[i]=1ll*pw1[i-1]*26%mod;
31     for(int i=1;i<=Maxx;i++) pw2[i]=1ll*pw2[i-1]*25%mod;
32     int i26=Inv(26);
33     for(int i=1;i<=Maxx;i++) iv1[i]=1ll*iv1[i-1]*i26%mod;
34 }
35 void Solve(vint &v,int n)
36 {
37     v.resize(100001);
38     for(int i=n;i<=100000;i++)    
39         v[i]=(v[i-1]+1ll*fac[i-1]*iv1[i]%mod*pw2[i-n]%mod*inv[i-n]%mod)%mod;
40 }
41 int Query(int n,int m)
42 {
43     if(n>m) return 0;
44     return 1ll*mp[n][m]*pw1[m]%mod*inv[n-1]%mod;
45 }
46 int main()
47 {
48     scanf("%d%s",&T,str+1),Pre(100000); 
49     int len=strlen(str+1);
50     Solve(mp[len],len);
51     while(T--)
52     {
53         scanf("%d",&op);
54         if(op==1) 
55         {
56             scanf("%s",str+1),len=strlen(str+1);
57             if(!mp.count(len)) Solve(mp[len],len);
58         }
59         else
60             scanf("%d",&rd),printf("%d\n",Query(len,rd));
61     }
62     return 0;
63 }
View Code

CF666E Forensic Examination

字符串菜鸡终于把这道i207M早就讲了的题A掉了

SAM上跑线段树合并

注意合并要新建点,因为原来的点还要用

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=1e6+50,M=9e6+60;
  6 
  7 int trs[N][26],fth[N],siz[N];
  8 int len[N],endp[N],ende[N];
  9 int lth,lng,tot,lst; 
 10 char str[N],rd[N];
 11 
 12 int root[N],val[M],vid[M],son[M][2];
 13 int T,n,id,t1,t2,t3,t4,ans,anss;
 14 
 15 int cnt,p[N],noww[N],goal[N],anc[N][20];
 16 
 17 int Insert(int ch)
 18 {
 19     int nde=lst,newn=++tot; lst=newn;
 20     siz[newn]=1,len[newn]=len[nde]+1;
 21     while(nde&&!trs[nde][ch])
 22         trs[nde][ch]=newn,nde=fth[nde];
 23     if(!nde) fth[newn]=1;
 24     else 
 25     {
 26         int tran=trs[nde][ch];
 27         if(len[tran]==len[nde]+1)
 28             fth[newn]=tran;
 29         else 
 30         {
 31             int rnde=++tot; len[rnde]=len[nde]+1;
 32             for(int i=0;i<=25;i++) trs[rnde][i]=trs[tran][i];
 33             fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde;
 34             while(nde&&trs[nde][ch]==tran)
 35                 trs[nde][ch]=rnde,nde=fth[nde];
 36         }
 37     }
 38     return newn;
 39 }
 40 
 41 void Pushup(int nde)
 42 {
 43     int ls=son[nde][0],rs=son[nde][1];
 44     if(val[ls]>=val[rs]) val[nde]=val[ls],vid[nde]=vid[ls];
 45     else val[nde]=val[rs],vid[nde]=vid[rs];
 46 }
 47 void Add(int &nde,int l,int r,int pos,int tsk)
 48 {
 49     if(!nde) nde=++id;
 50     if(l==r) 
 51         val[nde]+=tsk,vid[nde]=l;
 52     else
 53     {
 54         int mid=(l+r)>>1;
 55         if(pos<=mid) Add(son[nde][0],l,mid,pos,tsk);
 56         else Add(son[nde][1],mid+1,r,pos,tsk); Pushup(nde);
 57     }
 58 }
 59 int Merge(int x,int y,int l,int r)
 60 {
 61     if(!x||!y) return x+y;
 62     if(l==r)
 63     {
 64         val[x]=val[x]+val[y],vid[x]=l; 
 65         return x;
 66     }
 67     else
 68     {
 69         int mid=(l+r)>>1;
 70         son[x][0]=Merge(son[x][0],son[y][0],l,mid);
 71         son[x][1]=Merge(son[x][1],son[y][1],mid+1,r);
 72         Pushup(x); return x;
 73     }
 74 }
 75 void Query(int nde,int l,int r,int ll,int rr)
 76 {
 77     if(!nde) return;
 78     if(l>=ll&&r<=rr)
 79     {
 80         if(ans<val[nde]||(ans==val[nde]&&anss>vid[nde]))
 81             ans=val[nde],anss=vid[nde];
 82     }
 83     else
 84     {
 85         int mid=(l+r)>>1;
 86         if(mid>=ll) Query(son[nde][0],l,mid,ll,rr);
 87         if(mid<rr) Query(son[nde][1],mid+1,r,ll,rr);
 88     }
 89 }
 90 
 91 void Link(int f,int t)
 92 {
 93     noww[++cnt]=p[f];
 94     goal[cnt]=t,p[f]=cnt;
 95 }
 96 void DFS(int nde)
 97 {
 98     anc[nde][0]=fth[nde];
 99     for(int i=1;i<=19&&anc[nde][i-1];i++)
100         anc[nde][i]=anc[anc[nde][i-1]][i-1];
101     for(int i=p[nde];i;i=noww[i])
102         DFS(goal[i]),root[nde]=Merge(root[nde],root[goal[i]],1,n);// printf("%d-=-",val[root[nde]]);
103 }
104 
105 int main()
106 {
107     scanf("%s%d",str+1,&n);
108     lth=strlen(str+1),val[0]=-1,tot=1;
109     for(int i=1;i<=n;i++)
110     {
111         scanf("%s",rd+1);
112         lng=strlen(rd+1),lst=1;
113         for(int j=1;j<=lng;j++)
114         {
115             int newn=Insert(rd[j]-'a');
116             Add(root[newn],1,n,i,1);
117         }
118     }
119     int nde=1,mxl=0;
120     for(int i=1;i<=lth;i++)
121     {
122         int ch=str[i]-'a';
123         while(nde&&!trs[nde][ch])
124             nde=fth[nde],mxl=len[nde];
125         if(nde) nde=trs[nde][ch],mxl++;
126         else nde=1,mxl=0;
127         endp[i]=nde,ende[i]=mxl; 
128     }
129     for(int i=1;i<=tot;i++) Link(fth[i],i); DFS(1);
130 //    for(int i=1;i<=id;i++) 
131 //        printf("%d %d\n",val[i],vid[i]);
132     scanf("%d",&T);
133     while(T--)
134     {
135         scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
136         nde=endp[t4],mxl=t4-t3+1; 
137         if(ende[t4]<mxl)
138             printf("%d 0\n",t1);
139         else
140         {
141             for(int i=19;~i;i--)
142                 if(len[anc[nde][i]]>=mxl)
143                     nde=anc[nde][i];
144             ans=-1,anss=1e9;
145             Query(root[nde],1,n,t1,t2); 
146             ~ans?printf("%d %d\n",anss,ans):printf("%d 0\n",t1);
147         }
148     }
149     return 0;
150 }
View Code

Part 2

肥肠爆芡,这块整体咕咕了

一定补一定补

posted @ 2019-03-08 20:06  Speranza_Leaf  阅读(171)  评论(0)    收藏  举报