• 测试「20200912测试总结」


    考完后的心情:


    T1 「MZOI2020」快速班号变换

    简单DP题,没处理边界,(100 o 70)

    (f_{i,j}) 表示使得 (a) 串前 (i) 位变换到 (b) 串前 (j) 位的最小花费,则有转移:

    • (a_i) 变成 (b_j) ,则 (f_{i,j}=f_{i-1,j-1}+{ m{dist}}(a_i,b_j))
    • 删除 (a_i) ,则 (f_{i,j}=f_{i-1,j}+a_i)
    • 插入 (b_j) ,则 (f_{i,j}=f_{i,j-1}+b_j)

    ( ext{Code}:)

    memset(f,0x3f,sizeof(f));
    f[0][0]=0;
    for(int i=0;i<=n;++i)
    	for(int j=0;j<=m;++j)
    	{
    		if(i>=1&&j>=1) f[i][j]=min(f[i][j],f[i-1][j-1]+dis(a[i],b[j]));
    		if(j>=1) f[i][j]=min(f[i][j],f[i][j-1]+b[j]);
    		if(i>=1) f[i][j]=min(f[i][j],f[i-1][j]+a[i]);
    	}
    printf("%d
    ",f[n][m]);
    

    T2 「MZOI2020」魔导书

    考试的时候想了个错的贪心,理所应当地爆零了。

    假如已经选了一些书叠到了一起,此时上面最多能再叠 (up) 本书,对于剩下的书分类讨论:

    • 若存在一本书,使得它加入后不会改变 (up) ,即 (bgeq up-1) ,选择这样的书中 (a) 最大的加入。
    • 若不存在上述的书,则选择一本 (b) 尽量大的书,因为这样能使之后能加入的书尽量多。

    按这个思路贪心即可。

    ( ext{Code}:)

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define maxn 1000005
    #define Rint register int
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long lxl;
    const int mod=910666;
    
    template <typename T>
    inline void read(T &x)
    {
    	x=0;T f=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	x*=f;
    }
    
    struct Book
    {
    	int a,b;
    	Book(int a,int b):a(a),b(b){}
    	Book(){}
    	inline bool operator < (const Book &T)const
    	{
    		if(b==T.b) return a<T.a;
    		return b<T.b;
    	}
    }book[maxn];
    
    int n;
    
    struct Segment_Tree
    {
    	struct node
    	{
    		int l,r,Max;
    	}tree[maxn<<2];
    	#define ls (p<<1)
    	#define rs (p<<1|1)
    	int a[maxn];
    	inline int max(const int &x,const int &y)
    	{
    		return a[x]>a[y]?x:y;
    	}
    	inline void maintain(int p)
    	{
    		tree[p].Max=max(tree[ls].Max,tree[rs].Max);
    	}
    	inline void build(int p,int l,int r)
    	{
    		tree[p]=(node){l,r,0};
    		if(l==r) return void(tree[p].Max=l);
    		int mid=(l+r)>>1;
    		build(ls,l,mid);
    		build(rs,mid+1,r);
    		maintain(p);
    	}
    	inline void update(int p,int ps)
    	{
    		int l=tree[p].l,r=tree[p].r;
    		if(l==r) return void(tree[p].Max=0);
    		int mid=(l+r)>>1;
    		if(ps<=mid) update(ls,ps);
    		else update(rs,ps);
    		maintain(p);
    	}
    	inline int query(int p,int L,int R)
    	{
    		int l=tree[p].l,r=tree[p].r;
    		if(L<=l&&r<=R) return tree[p].Max;
    		int mid=(l+r)>>1,ans=0;
    		if(L<=mid) ans=max(ans,query(ls,L,R));
    		if(R>mid) ans=max(ans,query(rs,L,R));
    		return ans;
    	}
    }sta,stb;
    
    int main()
    {
    	// freopen("B.in","r",stdin);
    	read(n);
    	for(int i=1;i<=n;++i) read(book[i].a);
    	for(int i=1;i<=n;++i) read(book[i].b);
    	sort(book+1,book+n+1);
    	for(int i=1;i<=n;++i) sta.a[i]=book[i].a,stb.a[i]=book[i].b;
    	sta.build(1,1,n);sta.update(1,n);
    	stb.build(1,1,n);stb.update(1,n);
    	int up=book[n].b,ans=book[n].a%mod,cnt=1;
    	while(up>0&&cnt<n)
    	{
    		--up;
    		int p=lower_bound(book+1,book+n+1,Book(-1,up))-book;
    		int now=sta.query(1,p,n);
    		if(now) ans=(ans+book[now].a)%mod;
    		else
    		{
    			now=stb.tree[1].Max;
    			up=book[now].b;
    			ans=(ans+book[now].a)%mod;
    		}
    		++cnt;
    		sta.update(1,now);
    		stb.update(1,now);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

    T3 「MZOI2020」遗传因子

    考场上想出正解了,然后因为数组开小,(100 o 30)

    建一个AC自动机,在fail树上统计答案即可。

    感觉这东西挺套路的。

    ( ext{Code}:)

    #include <cstring>
    #include <cstdio>
    #include <string>
    #include <algorithm>
    #include <queue>
    #define maxn 10005
    #define maxnode 1000005
    using namespace std;
    
    template <typename T>
    inline void read(T &x)
    {
    	x=0;T f=1;char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    	x*=f;
    }
    
    struct edge
    {
    	int u,v,next;
    }e[maxnode];
    
    int head[maxnode],k;
    
    inline void add(int u,int v)
    {
    	e[k]=(edge){u,v,head[u]};
    	head[u]=k++;
    }
    
    int n,L[maxn],R[maxn];
    char s[maxnode],t[maxnode];
    
    int ch[maxnode][30],tree[maxnode][30],tot,fail[maxnode],book[maxnode];
    
    inline void insert(int id)
    {
    	int u=0;
    	for(int i=L[id];i<=R[id];++i)
    	{
    		int c=s[i]-'a'+1;
    		if(!ch[u][c]) ch[u][c]=tree[u][c]=++tot;
    		u=ch[u][c];
    	}
    	book[u]=id;
    }
    
    inline void get_fail()
    {
    	queue<int> q;
    	memset(fail,-1,sizeof(fail));
    	for(int i=1;i<=26;++i)
    		if(ch[0][i]) q.push(ch[0][i]),fail[ch[0][i]]=0;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();
    		for(int i=1;i<=26;++i)
    			if(ch[u][i])
    			{
    				fail[ch[u][i]]=ch[fail[u]][i];
    				q.push(ch[u][i]);
    			}
    			else ch[u][i]=ch[fail[u]][i];
    	}
    	for(int i=1;i<=tot;++i) if(~fail[i])
    		add(fail[i],i);
    }
    
    int f[maxnode],g[maxnode];
    
    inline void dfs(int u)
    {
    	if(book[u])
    	{
    		f[u]+=R[book[u]]-L[book[u]]+1;
    		++g[u];
    	}
    	for(int i=head[u];~i;i=e[i].next)
    	{
    		int v=e[i].v;
    		f[v]+=f[u];
    		g[v]+=g[u];
    		dfs(v);
    	}
    }
    
    int Ans[maxn],Sum;
    
    inline void Get_Ans(int u,int sum,int cnt)
    {
    	if(book[u])
    	{
    		Ans[book[u]]=(R[book[u]]-L[book[u]]+1)*cnt-sum;
    		Sum+=Ans[book[u]];
    	}
    	for(int i=1;i<=26;++i)
    	{
    		int v=tree[u][i];
    		if(!v) continue;
    		Get_Ans(v,sum+f[v],cnt+g[v]);
    	}
    }
    
    int main()
    {
    	// freopen("C.in","r",stdin);
    	read(n);
    	for(int i=1;i<=n;++i)
    	{
    		scanf(" %s",t+1);
    		L[i]=R[i-1]+1;
    		R[i]=L[i]+strlen(t+1)-1;
    		strcat(s+L[i],t+1);
    		insert(i);
    	}
    	memset(head,-1,sizeof(head));
    	get_fail();
    	dfs(0);
    	Get_Ans(0,f[0],g[0]);
    	printf("%d
    ",Sum);
    	for(int i=1;i<=n;++i)
    		printf("%d
    ",Ans[i]);
    	return 0;
    }
    
    

    死亡原因

    1. DP没处理边界。
    2. 数组开小。

    我退役罢

  • 相关阅读:
    linux:centos7开启指定端口,开放外网访问
    zookeeper 集群搭建
    单机安装zookeeper的3.4.7版本
    CentOS7下安装jdk1.8并配置环境变量,防火墙设置开关
    Redis分布式锁的正确实现方式
    MySQl5.7 忘记密码怎么办?
    Flink 之Window(窗口)
    Flink之Sink(文件、Kafka、Redis、Es、Mysql)
    Canal同步Mysql数据至Hbase
    Flink 之分流Select与Split
  • 原文地址:https://www.cnblogs.com/syc233/p/13657302.html
Copyright © 2020-2023  润新知