省选校内模拟D8

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;
}

猜你喜欢

转载自blog.csdn.net/strangeDDDF/article/details/87894936