因为改题太慢,两篇总结合一块写了。
馍旎6:
抄了一套UR(的题目
A. Yist
根号算法。
首先判-1即为判断是否有一个点能对其他点作贡献,且不存在于s序列中。
考虑单个点的贡献,假如第一轮贡献为$a$,之后每一轮的的贡献即为$a*2^{cnt}$
cnt为这个点在序列中出现的次数。然后这玩意拿等比数列求和就可以了。
然后出题人随便造个菊花图就能卡死你。
考虑根号算法,按每个点度数是否大于$sqrt{n}$分为大点和小点。
对于每个大点,统计时暴力扫与它相连的大点统计贡献,
大点同时累计自己对周围小点的贡献
小点暴力扫所有出边统计贡献,同时接受大点贡献
1 #include<bits/stdc++.h> 2 #define N 400050 3 #define pb push_back 4 const int mod=998244353,inv2=499122177; 5 using namespace std; 6 int s[N],n,m,k; 7 int w[N],d[N]; 8 int a[N],ts[N],val[N]; 9 vector<int>v[N],c[N]; 10 inline int qpow(int d,int z){ 11 int ret=1; 12 for(;z;z>>=1,d=1ll*d*d%mod) 13 if(z&1)ret=1ll*ret*d%mod; 14 return ret; 15 } 16 inline bool judge(){ 17 static bool pd[N]; 18 memset(pd,false,sizeof(pd)); 19 for(int i=1;i<=k;++i)pd[s[i]]=1; 20 for(int i=1;i<=n;++i) 21 for(int j=v[i].size()-1;~j;--j) 22 if(pd[i]&&!pd[v[i][j]]&&w[v[i][j]]) 23 return true; 24 return false; 25 } 26 bool cmp(const int &a,const int &b){ 27 return v[a].size()>v[b].size(); 28 } 29 int main(){ 30 for(int i=1;i<=n;++i){ 31 v[i].clear();c[i].clear(); 32 ts[i]=1;a[i]=val[i]=d[i]=0; 33 } 34 if(scanf("%d%d%d",&n,&m,&k)==EOF)return 0; 35 for(int i=1;i<=n;++i){ 36 scanf("%d",&w[i]); 37 v[i].clear();c[i].clear(); 38 ts[i]=1,a[i]=val[i]=d[i]=0; 39 } 40 for(int i=1;i<=k;++i)scanf("%d",&s[i]); 41 for(int i=1,x,y;i<=m;++i){ 42 scanf("%d%d",&x,&y); 43 v[x].pb(y);v[y].pb(x); 44 } 45 if(judge()){puts("-1");return main();} 46 const int sq=sqrt(n); 47 for(int i=1;i<=n;++i){ 48 sort(v[i].begin(),v[i].end(),cmp); 49 d[i]=v[i].size()>=sq?1:0; 50 } 51 for(int i=1;i<=n;++i) 52 if(!d[i]){ 53 for(int j=0,sz=v[i].size();j<sz&&d[v[i][j]];++j) 54 c[i].pb(0); 55 } 56 int ans=0; 57 58 for(int i=1,g;i<=k;++i){ 59 g=s[i];ts[g]<<=1; 60 if(ts[g]>=mod)ts[g]-=mod; 61 if(d[g]){ 62 ++val[g]; 63 for(int j=0,sz=v[g].size();j<sz&&d[v[g][j]];++j) 64 (a[v[g][j]]+=w[v[g][j]])%=mod; 65 } 66 else{ 67 for(int j=0,sz=v[g].size();j<sz;++j){ 68 (a[v[g][j]]+=w[v[g][j]])%=mod; 69 if(d[v[g][j]]){ 70 (a[g]+=1ll*w[g]*(val[v[g][j]]-c[g][j])%mod)%=mod; 71 c[g][j]=val[v[g][j]]; 72 } 73 } 74 } 75 w[g]=1ll*w[g]*inv2%mod; 76 } 77 for(int g=1;g<=n;++g) 78 if(!d[g]){ 79 for(int j=0,sz=v[g].size();j<sz&&d[v[g][j]];++j) 80 (a[g]+=1ll*w[g]*(val[v[g][j]]-c[g][j])%mod)%=mod; 81 } 82 for(int i=1;i<=n;++i){ 83 ans+=1ll*a[i]*ts[i]%mod*qpow(ts[i]-1,mod-2)%mod; 84 if(ans>=mod)ans-=mod; 85 } 86 cout<<ans<<endl; 87 return main(); 88 }
B. Ernd
$SAM+dp$
在串前加字符相当于在$parent_tree$上走,在串后加字符相当于在$SAM$上走。
发现对于$parent_tree$上一个节点,一定是把它先走到当前点的最大长度再转移。
拓扑dp,最后输出$dp[las]$
1 #include<bits/stdc++.h> 2 #define N 400050 3 #define ull unsigned long long 4 using namespace std; 5 int n,f[N]; 6 int du[N]; 7 long long dp[N],ans; 8 char s[N]; 9 int tot=1,las=1; 10 int he[N],ne[N],to[N],cnt; 11 inline void addedge(int x,int y){ 12 to[++cnt]=y;ne[cnt]=he[x];he[x]=cnt; 13 } 14 struct node{ 15 int len,fa; 16 int ch[26]; 17 }tr[N]; 18 inline void add(int c){ 19 int np=++tot,p=las;las=np;f[np]=1; 20 tr[np].len=tr[p].len+1; 21 for(;p&&!tr[p].ch[c];p=tr[p].fa)tr[p].ch[c]=np; 22 if(!p)return tr[np].fa=1,void(); 23 int q=tr[p].ch[c]; 24 if(tr[q].len==tr[p].len+1)return tr[np].fa=q,void(); 25 int nq=++tot;tr[nq]=tr[q]; 26 tr[nq].len=tr[p].len+1; 27 tr[q].fa=tr[np].fa=nq; 28 for(;p&&tr[p].ch[c]==q;p=tr[p].fa)tr[p].ch[c]=nq; 29 } 30 inline void tope(){ 31 for(int i=1;i<=tot;++i) 32 for(int j=0;j<26;++j) 33 ++du[tr[i].ch[j]]; 34 queue<int>q;q.push(1); 35 while(q.size()){ 36 int g=q.front();q.pop(); 37 // printf("f[%d]=%d ",g,f[g]); 38 dp[g]=max(dp[g],dp[tr[g].fa]+f[g]*(tr[g].len-tr[tr[g].fa].len)); 39 for(int i=0,t;i<26;++i){ 40 t=tr[g].ch[i];if(!t)continue; 41 dp[t]=max(dp[t],dp[g]+1ll*f[t]*(tr[t].len-tr[g].len)); 42 --du[t]; 43 if(!du[t])q.push(t); 44 } 45 } 46 ans=dp[las]; 47 } 48 inline void dfs(int g){ 49 for(int i=he[g];i;i=ne[i]) 50 dfs(to[i]),f[g]+=f[to[i]]; 51 } 52 int main(){ 53 scanf("%d%s",&n,s+1); 54 for(int i=1;i<=n;++i)add(s[i]-'a'); 55 for(int i=2;i<=tot;++i)addedge(tr[i].fa,i); 56 dfs(1); 57 tope(); 58 cout<<ans<<endl; 59 return 0; 60 }
C. Sanrd
大神题,改了一下午加一晚上加一早上才改过来。
其实还是挺好理解的,就是代码难打
1 #include<bits/stdc++.h> 2 #define N 500050 3 #define ull long long 4 const int mod=998244353; 5 using namespace std; 6 int dp1[N],dp2[N],n,a[N],an1,an2,pr[N][2],pre[N]; 7 ull f[N],f2[N],al,w[N][2]; 8 struct BIT{ 9 int ct[N],po[N]; 10 inline void clear(){ 11 memset(ct,0,sizeof(int)*(n+1)); 12 memset(po,0,sizeof(int)*(n+1)); 13 } 14 inline void add(int x,int v,int id=0){ 15 while(x){ 16 if(v>ct[x]) 17 ct[x]=v,po[x]=id; 18 x-=x&-x; 19 } 20 } 21 inline int ask(int x){ 22 int ret=0; 23 while(x<=n) 24 ret=max(ret,ct[x]),x+=x&-x; 25 return ret; 26 } 27 inline int ask2(int x){ 28 int ret=0,r2=0; 29 while(x<=n){ 30 if(ct[x]>ret)ret=ct[x],r2=po[x]; 31 x+=x&-x; 32 } 33 return r2; 34 } 35 }b; 36 struct BIT2{ 37 ull ct[N];int tim[N],cnt; 38 inline void clear(){++cnt;} 39 inline void add(int x,int v){ 40 while(x){ 41 if(tim[x]!=cnt)tim[x]=cnt,ct[x]=0; 42 ct[x]+=v;x-=x&-x; 43 } 44 } 45 inline ull ask(int x){ 46 ull ret=0; 47 while(x<=n){ 48 if(tim[x]!=cnt)tim[x]=cnt,ct[x]=0; 49 ret+=ct[x]; 50 x+=x&-x; 51 } 52 ret%=mod; 53 return ret; 54 } 55 }b2; 56 vector<int>v[N]; 57 #define pb push_back 58 inline void init1(){ 59 b.clear(); 60 for(int i=1;i<=n;++i){ 61 dp2[i]=b.ask(a[i])+1; 62 an2=max(an2,dp2[i]); 63 b.add(a[i],dp2[i]); 64 v[dp2[i]].push_back(i); 65 // printf("dp2[%d]=%d ",i,dp2[i]); 66 } 67 for(int i=0,sz=v[an2].size();i<sz;++i)f[v[an2][i]]=1; 68 for(int i=an2;i>1;--i){ 69 int j=v[i-1].size()-1,k=v[i].size()-1; 70 b2.clear(); 71 while(j>=0){ 72 while(k>=0&&v[i][k]>v[i-1][j]){ 73 b2.add(a[v[i][k]],f[v[i][k]]); 74 --k; 75 } 76 f[v[i-1][j]]=b2.ask(1)-b2.ask(a[v[i-1][j]]); 77 if(f[v[i-1][j]]<0)f[v[i-1][j]]+=mod; 78 --j; 79 } 80 } 81 // for(int i=1;i<=n;++i)printf("f[%d]=%lld f2:%lld ",i,f[i],f2[i]); 82 for(int i=0,sz=v[1].size();i<sz;++i)f2[v[1][i]]=1; 83 for(int i=1;i<an2;++i){ 84 int j=0,k=0,sz=v[i].size(),sz2=v[i+1].size(); 85 b2.clear(); 86 while(j<sz2){ 87 while(k<sz&&v[i][k]<v[i+1][j]){ 88 b2.add(a[v[i][k]],f2[v[i][k]]); 89 ++k; 90 } 91 f2[v[i+1][j]]=b2.ask(a[v[i+1][j]]); 92 f[v[i+1][j]]*=f2[v[i+1][j]]; 93 f[v[i+1][j]]%=mod; 94 ++j; 95 } 96 } 97 for(int j=0,sz=v[an2].size();j<sz;++j)al+=f[v[an2][j]]; 98 al%=mod; 99 // for(int i=1;i<=n;++i)printf("f[%d]=%lld f2:%lld ",i,f[i],f2[i]); 100 // cout<<"al:"<<al<<endl; 101 } 102 int pd[N]; 103 struct BIT3{ 104 int ct[N]; 105 inline void add(int x,int v){ 106 while(x<=n){ 107 if(v>ct[x])ct[x]=v; 108 x+=x&-x; 109 } 110 } 111 inline int ask(int x){ 112 int ret=0; 113 while(x)ret=max(ret,ct[x]),x-=x&-x; 114 return ret; 115 } 116 }b3; 117 struct BIT4{ 118 int q[N][2],ct[N]; 119 ull qq[N][2]; 120 inline void init(){ 121 for(int i=1;i<=n;++i)qq[i][0]=qq[i][1]=q[i][0]=q[i][1]=-1; 122 } 123 inline void add(int i){ 124 int x=a[i]; 125 while(x<=n){ 126 if(dp1[i]>ct[x]){ 127 ct[x]=dp1[i]; 128 q[x][0]=qq[x][0]=q[x][1]=qq[x][1]=-1; 129 } 130 if(ct[x]==dp1[i]&&qq[x][0]<0&&w[i][0]>=0){ 131 q[x][0]=i; 132 qq[x][0]=w[i][0]; 133 if(w[i][1]>=0){ 134 q[x][1]=i; 135 qq[x][1]=w[i][1]; 136 } 137 } 138 else if(ct[x]==dp1[i]&&qq[x][1]<0){ 139 if(w[i][0]>=0&&w[i][0]!=qq[x][0]){ 140 q[x][1]=i; 141 qq[x][1]=w[i][0]; 142 } 143 if(w[i][1]>=0&&w[i][1]!=qq[x][0]){ 144 q[x][1]=i; 145 qq[x][1]=w[i][1]; 146 } 147 } 148 x+=x&-x; 149 } 150 } 151 inline void ask(int i){ 152 int x=a[i]; 153 while(x){ 154 if(ct[x]==dp1[i]-1&&w[i][0]<0&&qq[x][0]>=0){ 155 pr[i][0]=q[x][0]; 156 w[i][0]=qq[x][0]; 157 if(qq[x][1]>=0){ 158 pr[i][1]=q[x][1]; 159 w[i][1]=qq[x][1]; 160 } 161 } 162 else if(ct[x]==dp1[i]-1&&w[i][1]<0&&qq[x][0]>=0){ 163 if(qq[x][0]>=0&&qq[x][0]!=w[i][0]){ 164 pr[i][1]=q[x][0]; 165 w[i][1]=qq[x][0]; 166 } 167 if(qq[x][1]>=0&&qq[x][1]!=w[i][0]){ 168 pr[i][1]=q[x][1]; 169 w[i][1]=qq[x][1]; 170 } 171 } 172 x-=x&-x; 173 } 174 } 175 }b4; 176 inline void init2(){ 177 b4.init(); 178 for(int i=1;i<=n;++i){ 179 dp1[i]=b3.ask(a[i])+1; 180 an1=max(an1,dp1[i]); 181 b3.add(a[i],dp1[i]); 182 // printf("dp1[%d]=%d ",i,dp1[i]); 183 } 184 for(int i=1;i<=n;++i){ 185 w[i][0]=w[i][1]=-1; 186 //if(dp1[i]!=1) 187 b4.ask(i); 188 if(w[i][0]>=0||dp1[i]==1){ 189 w[i][0]+=f[i]; 190 if(dp1[i]==1)++w[i][0]; 191 } 192 if(w[i][1]>=0)w[i][1]+=f[i]; 193 w[i][0]%=mod;w[i][1]%=mod; 194 // printf("i:%d w0:%lld w1:%lld p0:%d p1:%d ",i,w[i][0],w[i][1],pr[i][0],pr[i][1]); 195 b4.add(i); 196 } 197 } 198 inline void dfs2(int g){ 199 if(!g)return;dfs2(pre[g]); 200 printf("%d ",g); 201 } 202 inline void getans(){ 203 b.clear(); 204 printf("%d ",an1); 205 for(int i=1;i<=n;++i){ 206 dp2[i]=0; 207 if(pd[i]){ 208 printf("%d ",i); 209 continue; 210 } 211 dp2[i]=b.ask(a[i])+1; 212 pre[i]=b.ask2(a[i]); 213 b.add(a[i],dp2[i],i); 214 // printf("pre[%d]=%d dp2:%d ",i,pre[i],dp2[i]); 215 } 216 printf(" %d ",an2); 217 for(int i=1;i<=n;++i) 218 if(dp2[i]==an2)return dfs2(i); 219 } 220 inline void dfs(int g,ull t){ 221 if(!g)return getans(); 222 pd[g]=1; 223 if((t+w[g][0])%mod!=al)dfs(pr[g][0],(t+f[g])%mod); 224 else dfs(pr[g][1],(t+f[g])%mod); 225 } 226 int main(){ 227 // freopen("sanrd2.in","r",stdin);freopen("my.out","w",stdout); 228 scanf("%d",&n); 229 for(int i=1;i<=n;++i)scanf("%d",&a[i]); 230 init1();init2(); 231 memset(pd,0,sizeof(int)*(n+1)); 232 for(int i=1;i<=n;++i){ 233 // cout<<i<<" "<<w[i][0]<<" "<<w[i][1]<<endl; 234 if(dp1[i]==an1){ 235 if(w[i][0]!=-1&&w[i][0]!=al){ 236 pd[i]=1;dfs(pr[i][0],f[i]); 237 return 0; 238 } 239 if(w[i][1]!=-1&&w[i][1]!=al){ 240 pd[i]=1;dfs(pr[i][1],f[i]); 241 return 0; 242 } 243 } 244 } 245 puts("-1");return 0; 246 }
馍旎7:
A. 翻转硬币/星空
原来写过一遍的题,然而也忘得差不多了。
用到了差分的思想。
考虑维护原01序列的差分序列。
则原先的区间操作对应新的对有距离限制的两个点取反,
转化为求最少多少次操作使得差分序列全为0。
然后对每个为1点求出与其它为1的点的距离。
然后跑状压dp就可以了。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<queue> 5 #define reg register 6 #define N 1100000 7 using namespace std; 8 int m,n,k; 9 int a[120]; 10 int b[120]; 11 int pos[N]; 12 int g1[N]; 13 int g2[N]; 14 int dis[N][2]; 15 int w[1<<20]; 16 int dp[1<<20]; 17 void bfs() 18 { 19 memset(w,0x3f,sizeof(w)); 20 a[0]=0; 21 for(int i=1;i<=n;++i) 22 if(g2[i])a[++a[0]]=i,pos[i]=a[0]; 23 queue<int>q; 24 int al,g,y; 25 for(int i=1;i<=a[0];++i) 26 { 27 al=1; 28 q.push(a[i]);dis[a[i]][0]=dis[a[i]][1]=0; 29 while(al<a[0]&&q.size()) 30 { 31 g=q.front();q.pop(); 32 for(int j=1;j<=m;++j) 33 { 34 if(g-b[j]>0&&dis[g-b[j]][0]<i){ 35 y=g-b[j]; 36 dis[y][0]=i; 37 dis[y][1]=dis[g][1]+1; 38 if(pos[y]&&y!=a[i]) 39 w[(1<<i-1)|(1<<pos[y]-1)]=dis[y][1]; 40 else 41 q.push(y); 42 } 43 if(g+b[j]<=n&&dis[g+b[j]][0]<i){ 44 y=g+b[j]; 45 dis[y][0]=i; 46 dis[y][1]=dis[g][1]+1; 47 if(pos[y]&&y!=a[i]) 48 w[(1<<i-1)|(1<<pos[y]-1)]=dis[y][1]; 49 else 50 q.push(y); 51 } 52 } 53 } 54 while(q.size())q.pop(); 55 } 56 } 57 void work() 58 { 59 memset(dp,0x3f,sizeof(dp)); 60 const int maxn=1<<a[0];dp[maxn-1]=0; 61 reg int t1,t2; 62 for(int i=maxn-1;i;--i) 63 for(int j=i;j;j-=j&-j){ 64 t1=j&-j; 65 for(int o=j-(j&-j);o;o-=o&-o){ 66 t2=o&-o; 67 dp[i^t1^t2]=min(dp[i^t1^t2],dp[i]+w[t1|t2]); 68 } 69 } 70 if(dp[0]>5000000)dp[0]=-1; 71 cout<<dp[0]<<endl; 72 } 73 int main() 74 { 75 scanf("%d%d%d",&n,&k,&m); 76 for(int i=1;i<=k;++i) 77 scanf("%d",&a[i]),g1[a[i]]=1; 78 ++n; 79 for(int i=1;i<=m;++i) 80 scanf("%d",&b[i]); 81 for(int i=1;i<=n;++i) 82 g2[i]=g1[i]^g1[i-1]; 83 bfs(); 84 work(); 85 return 0; 86 }
B. 回文子串
其实还是比较水的一道题,除了样例弱一点没啥
然后维护答案可以用分快or线段树or树状数组。
求回文串可以用$PAM or Manacher or hash$
再加一个对拍就A了。上面的可以没有,但对拍必须有
1 #include<bits/stdc++.h> 2 #define N 50050 3 #define ull unsigned long long 4 using namespace std; 5 int bl[N]; 6 char s[N]; 7 int n,sq,m,K; 8 ull po[N],hs[N],hs2[N]; 9 const ull P=131; 10 inline void geths(int l,int r){ 11 hs[l-1]=hs[r+1]=hs2[l-1]=hs2[r+1]=0; 12 for(int i=l;i<=r;++i)hs[i]=hs[i-1]*P+s[i]; 13 for(int i=r;i>=l;--i)hs2[i]=hs2[i+1]*P+s[i]; 14 } 15 struct seg1{ 16 int tag[N<<2]; 17 inline void down(int g){ 18 tag[g<<1]=tag[g<<1|1]=tag[g]; 19 tag[g]=0; 20 } 21 inline void change(int g,int l,int r,int x,int y,int c){ 22 if(l>y||r<x)return; 23 if(l>=x&&r<=y){tag[g]=c;return;} 24 const int m=l+r>>1; 25 if(tag[g])down(g); 26 change(g<<1,l,m,x,y,c);change(g<<1|1,m+1,r,x,y,c); 27 } 28 inline void getstr(int g,int l,int r,int x,int y){ 29 if(l>y||r<x)return; 30 if(l==r){if(tag[g])s[l]=tag[g];return;} 31 const int m=l+r>>1;if(tag[g])down(g); 32 getstr(g<<1,l,m,x,y);getstr(g<<1|1,m+1,r,x,y); 33 } 34 }str; 35 struct seg2{ 36 int sum[N<<2],tag[N<<2]; 37 inline void upd(int g){ 38 sum[g]=sum[g<<1]+sum[g<<1|1]; 39 } 40 inline void down(int g,int l,int m,int r){ 41 tag[g<<1]=tag[g<<1|1]=tag[g]; 42 if(tag[g]==1)sum[g<<1]=m-l+1,sum[g<<1|1]=r-m; 43 else sum[g<<1]=sum[g<<1|1]=0; 44 tag[g]=0; 45 } 46 inline void change(int g,int l,int r,int x,int y,int v){ 47 if(l>y||r<x)return; 48 if(l>=x&&r<=y){ 49 sum[g]=v>0?r-l+1:0; 50 tag[g]=v; 51 return; 52 } 53 const int m=l+r>>1; 54 if(tag[g])down(g,l,m,r); 55 change(g<<1,l,m,x,y,v);change(g<<1|1,m+1,r,x,y,v); 56 upd(g); 57 } 58 inline int ask(int g,int l,int r,int x,int y){ 59 if(l>y||r<x)return 0; 60 if(l>=x&&r<=y)return sum[g]; 61 const int m=l+r>>1; 62 if(tag[g])down(g,l,m,r); 63 return ask(g<<1,l,m,x,y)+ask(g<<1|1,m+1,r,x,y); 64 } 65 }tr[52]; 66 inline void init(){ 67 geths(1,n); 68 for(int len=2;len<=K;++len){ 69 for(int i=len,j;i<=n;++i){ 70 j=i-len+1; 71 if(hs[i]-hs[j-1]*po[len]==hs2[j]-hs2[i+1]*po[len]) 72 tr[len].change(1,1,n,i,i,1); 73 } 74 } 75 } 76 inline void work1(int l,int r,int c){ 77 str.change(1,1,n,l,r,c); 78 for(int len=2;len<=K;++len) 79 tr[len].change(1,1,n,l+len-1,r,1); 80 for(int len=2;len<=K;++len) 81 tr[len].change(1,1,n,r+1,min(n,r+len-1),-1), 82 tr[len].change(1,1,n,l,min(l+len-2,n),-1); 83 int lm,rm; 84 85 lm=max(r-K+2,1);rm=min(r+K,n); 86 str.getstr(1,1,n,lm,rm); 87 geths(lm,rm); 88 // printf("lm:%d rm:%d ",lm,rm); 89 for(int len=2;len<=K;++len){ 90 for(int i=r+1,j;i<=rm;++i){ 91 j=i-len+1; 92 if(j>r)break; 93 if(j<=0)continue; 94 // puts("yes1"); 95 if(hs[i]-hs[j-1]*po[len]==hs2[j]-hs2[i+1]*po[len]) 96 tr[len].change(1,1,n,i,i,1);//,cout<<i<<" ri "<<len<<endl; 97 } 98 } 99 lm=max(l-K,1);rm=min(l+K-1,n); 100 rm=min(rm,r); 101 str.getstr(1,1,n,lm,rm); 102 geths(lm,rm); 103 // printf("lm:%d rm:%d ",lm,rm); 104 for(int len=2;len<=K;++len){ 105 for(int i=l,j;i<=rm;++i){ 106 j=i-len+1; 107 if(j>=l)break;if(j<=0)continue; 108 // puts("yes2"); 109 if(hs[i]-hs[j-1]*po[len]==hs2[j]-hs2[i+1]*po[len]) 110 tr[len].change(1,1,n,i,i,1);//,cout<<i<<" le "<<len<<endl; 111 } 112 } 113 // cout<<tr[2].sum[1]<<" "<<tr[3].sum[1]<<endl; 114 } 115 inline int getans(int l,int r){ 116 int ret=r-l+1; 117 for(int len=2;len<=K;++len) 118 ret+=tr[len].ask(1,1,n,l+len-1,r); 119 return ret; 120 } 121 int main(){ 122 scanf("%s%d%d",s+1,&K,&m); 123 n=strlen(s+1);sq=sqrt(n)+1; 124 po[0]=1;for(int i=1;i<=n;++i)po[i]=po[i-1]*P; 125 init(); 126 char S[3]; 127 for(int i=1,op,x,y;i<=m;++i){ 128 // cout<<"i::"<<i<<endl; 129 scanf("%d",&op); 130 if(op==1){ 131 scanf("%d%d%s",&x,&y,S); 132 work1(x,y,S[0]); 133 } 134 else{ 135 scanf("%d%d",&x,&y); 136 printf("%d ",getans(x,y)); 137 } 138 } 139 return 0; 140 }
C. 最大价值
大神T3,%%%skyh考场切掉(然而没开long long 挂得还不如暴力xswl)
当所选序列确定以后,一定是按a从小到大放。
首先60分可以直接按a从小到大排序,然后大力dp。
然后满分可以康这位大神的博客
1 #include<bits/stdc++.h> 2 #define N 300050 3 #define LL long long 4 using namespace std; 5 struct node{ 6 LL a,b; 7 friend bool operator <(const node &x,const node &y){ 8 return x.a==y.a?x.b<y.b:x.a<y.a; 9 } 10 }q[N]; 11 struct Splay{ 12 LL val[N],tag[N]; 13 int fa[N],ch[N][2],sz[N],rt,tot; 14 inline int Get(int x){return ch[fa[x]][1]==x;} 15 inline void upd(int g){sz[g]=sz[ch[g][0]]+sz[ch[g][1]]+1;} 16 inline void rotate(int x){ 17 int y=fa[x],z=fa[y],p=Get(x),w=ch[x][p^1]; 18 if(w)fa[w]=y;ch[y][p]=w; 19 if(z)ch[z][Get(y)]=x;fa[x]=z; 20 fa[y]=x;ch[x][p^1]=y; 21 upd(y);upd(x); 22 } 23 inline void push1(int g,LL v){if(!g||!v)return;val[g]+=v;tag[g]+=v;} 24 inline void down(int x){push1(ch[x][0],tag[x]),push1(ch[x][1],tag[x]);tag[x]=0;} 25 inline void pushall(int x){if(!x)return;down(x);} 26 inline void splay(int x){while(fa[x])rotate(x);rt=x;} 27 inline void insert(int i){ 28 ++tot;sz[tot]=1; 29 if(!rt){rt=tot;val[rt]=q[i].b;return;} 30 LL a=q[i].a,b=q[i].b; 31 int x=rt,rk=0; 32 while(1){ 33 down(x); 34 if(a*(rk+sz[ch[x][0]])+b>val[x]){ 35 if(ch[x][0])x=ch[x][0]; 36 else{ch[x][0]=tot;fa[tot]=x;break;} 37 } 38 else{ 39 rk+=sz[ch[x][0]]+1; 40 if(ch[x][1])x=ch[x][1]; 41 else{ch[x][1]=tot;fa[tot]=x;break;} 42 } 43 } 44 val[tot]=a*rk+b; 45 splay(tot);push1(ch[rt][1],a); 46 } 47 inline void bl(int g,LL &ans){ 48 down(g); 49 if(ch[g][0])bl(ch[g][0],ans); 50 ans+=val[g]; 51 printf("%lld ",ans); 52 if(ch[g][1])bl(ch[g][1],ans); 53 } 54 }s; 55 namespace ae86{ 56 const int bufl=1<<15; 57 char buf[bufl],*s=buf,*t=buf; 58 inline int fetch(){ 59 if(s==t){t=(s=buf)+fread(buf,1,bufl,stdin);if(s==t)return EOF;} 60 return*s++; 61 } 62 inline LL read(){ 63 LL a=0,b=1,c=fetch(); 64 while(!isdigit(c))b^=c=='-',c=fetch(); 65 while(isdigit(c))a=a*10+c-48,c=fetch(); 66 return b?a:-a; 67 } 68 } 69 using ae86::read; 70 int n; 71 int main(){ 72 n=read(); 73 for(int i=1;i<=n;++i)q[i].a=read(),q[i].b=read(); 74 sort(q+1,q+n+1);LL ans=0; 75 for(int i=1;i<=n;++i)s.insert(i); 76 s.bl(s.rt,ans); 77 return 0; 78 }