T1
- 题目看了半天
- 数据结构学傻
- 树状数组可以干的事写了个主席树
- 主席树还和动态开点线段树写混了
- 最后交的比较慌,没检查空间,成功爆零
- 改过以后由于常数巨大喜提75分
考场代码75pts
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define ll long long
using namespace std;
const ll N=5e5+1;
ll t[N],f[N],root[N],maxn[N*20],a[N],lc[N*20],rc[N*20],tot=0,n,ans=0,MAX;
inline ll read()
{
ll num=0;
char ch=getchar();
while(0==isdigit(ch))ch=getchar();
while(0!=isdigit(ch)) num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
return num;
}
void update(ll &o,ll L,ll R,ll last,ll x,ll v){
o=++tot;
lc[o]=lc[last],rc[o]=rc[last],maxn[o]=maxn[last];
if(L==R){maxn[o]=max(maxn[o],v);return;}
ll M=L+R>>1;
if(x<=M)update(lc[o],L,M,lc[last],x,v);
else update(rc[o],M+1,R,rc[last],x,v);
maxn[o]=max(maxn[lc[o]],maxn[rc[o]]);
}
void query(ll o,ll L,ll R,ll ql,ll qr){
ll M=L+R>>1;
if(!o)return;
if(ql<=L&&R<=qr){
MAX=max(MAX,maxn[o]);
return ;
}
if(ql<=M)query(lc[o],L,M,ql,qr);
if(M<qr)query(rc[o],M+1,R,ql,qr);
}
int main()
{
freopen("fc.in","r",stdin);
freopen("fc.out","w",stdout);
n=read();
rep(i,1,n)t[i]=read();
rep(i,1,n)a[i]=read();
rep(i,1,n){
ll pos=0;
MAX=0;
query(root[max(1LL*0,i-t[i])],1,n,1,i);
f[i]=max(f[i],MAX+t[i]*a[i]);
if(i+t[i]<=n)update(root[i],1,n,root[i-1],i+t[i],f[i]);
else root[i]=root[i-1];
}
rep(i,1,n)ans=max(ans,f[i]);
cout<<ans;
return 0;
}
100pts
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define ll long long
using namespace std;
const ll N=2e6;
ll t[N],f[N],c[N],a[N],n,ans=0,MAX;
inline ll read()
{
ll num=0;
char ch=getchar();
while(0==isdigit(ch))ch=getchar();
while(0!=isdigit(ch)) num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
return num;
}
ll lowbit(ll x){return x&-x;}
ll query(ll x){ll MAX=0;while(x)MAX=max(MAX,c[x]),x-=lowbit(x);return MAX;}
void update(ll x,ll v){while(x<=n)c[x]=max(c[x],v),x+=lowbit(x);}
priority_queue<pair<ll,ll> > q;
int main()
{
freopen("fc.in","r",stdin);
freopen("fc.out","w",stdout);
n=read();
rep(i,1,n)t[i]=read();
rep(i,1,n)a[i]=read();
rep(i,1,n){
f[i]=a[i]*t[i];
q.push(make_pair(-i-t[i],i));
}
rep(i,1,n){
ll pos=0;
while(q.size()){
int x=q.top().first;
int id=q.top().second;
if(-x>i)break;
q.pop();
update(id,f[id]);
}
MAX=query(max(1LL*0,i-t[i]));
f[i]=max(f[i],MAX+t[i]*a[i]);
}
rep(i,1,n)ans=max(ans,f[i]);
cout<<ans;
return 0;
}
T2
30pts
- 就是统计原串中本质不同的字串的个数
- 建出后缀自动机答案就是\sum max[i]-max[pre[i]] + 1
- 输出方案
- 直接在后缀自动机上按照ACGT的顺序DFS,到一个位置输出即可
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define ll long long
using namespace std;
const int N=2e5+100;
int op,n,tmp,len,to[N][200],maxn[N],pre[N];
char s[N];
ll ans=0;
void insert(int c){
int p=tmp,x=++n,q; tmp=n,maxn[x]=maxn[p]+1;
while(p&&!to[p][c])to[p][c]=x,p=pre[p];
if(!p){pre[x]=1;return;}
if(maxn[q=to[p][c]]==maxn[p]+1)pre[x]=q;
else{
int y=++n; maxn[y]=maxn[p]+1;
memcpy(to[y],to[q],sizeof(to[q]));
pre[y]=pre[q],pre[q]=pre[x]=y;
while(to[p][c]==q)to[p][c]=y,p=pre[p];
}
}
void work(int x,string S){
cout<<S<<"\n";
if(to[x]['A']){
work(to[x]['A'],S+"A");
}
if(to[x]['C']){
work(to[x]['C'],S+"C");
}
if(to[x]['G']){
work(to[x]['G'],S+"G");
}
if(to[x]['T']){
work(to[x]['T'],S+"T");
}
}
int main()
{
freopen("copy.in","r",stdin);
freopen("copy.out","w",stdout);
scanf("%d",&n);
scanf("%s",s+1);
scanf("%d",&op);
tmp=n=1; len=strlen(s+1);
rep(i,1,len)insert(s[i]);
rep(i,1,n)ans+=(ll)(maxn[i]-maxn[pre[i]]);
if(op)work(1,"");
printf("%lld\n",ans+1);
return 0;
}