11.4离线赛

来源:互联网 发布:工商业的软件 编辑:程序博客网 时间:2024/06/09 21:56

一、猴子除草

数据:对于100%,n∈[1,1e5]

显然的二分。但是只有95分。后来发现如果m==1时,直接出就有问题了,要特判掉。

二、机器人

数据:对于40%,n∈[1,100],k∈[1,5]
对于90%,n∈[1,100000],k∈[1,16]
对于100%,n∈[1,100000],k∈[1,20]

对于40%,可以直接全排所有颜色,然后再求一遍逆序对。如果进行亦凡预处理,在O(K)时间内求出逆序对的话,可以有70分。满分是对颜色K进行状压,表示前几种数用这些颜色是的最小交换次数。挺简单的。

考试时写的k^2*2^k,这个算一下复杂度只有90分,只是卡到了100分。正解是k * 2^k,同样是先预处理,把一个数i放到j里面时造成的贡献值。预处理的复杂度是一样的。

还要注意内存。这道题内存要很抠才行,开大一点点都不行。

Code:

#include<bits/stdc++.h>#define ll long long#define M 100005using namespace std;int A[M],cnt[21],lb[1<<20];ll dp[1<<20],C[21][20],cost[21][1<<20];//开大一点就错int main(){    int n,m;    scanf("%d%d",&n,&m);    for(int i=0;i<n;i++)scanf("%d",&A[i]),A[i]--;    memset(cost,0,sizeof cost);    memset(cnt,0,sizeof cnt);    for(int i=0;i<(1<<m);i++)dp[i]=2e10;    for(int i=0;i<m;i++)lb[1<<i]=i,dp[1<<i]=0;    for(int i=n-1;i>=0;i--){        for(int j=0;j<m;j++)            if(A[i]!=j)C[A[i]][j]+=cnt[j];        cnt[A[i]]++;    }    for(int i=0;i<m;i++)//预处理        for(int j=1;j<(1<<m);j++)            if(j&(1<<i))continue;            else{                int k=j&-j;                int x=j-k;                cost[i][j]=cost[i][x]+C[i][lb[k]];            }    for(int i=0;i<(1<<m);i++)//状压        for(int j=0;j<m;j++)            if(i&(1<<j))continue;            else{                int now=i|(1<<j);                dp[now]=min(dp[now],dp[i]+cost[j][i]);            }    printf("%lld\n",dp[(1<<m)-1]);    return 0;}

三、树上路径相交

数据:
这里写图片描述

前40分用bitset模拟就行。写的好有60分。60分其实是判断两条路径是否有交点,用LCA就行了。80分的链是按照右端点排序后直接求值。

正解和Paths很像,也是按照LCA先排序,这里按照LCA从浅到深,然后直接算值就行了。因为两个路径有交点,那么其中一个LCA肯定在另一个路径上,只所以要判断LCA上有多少个路径经过就行了。这样算也不会有重复和漏算,因为从上到下,那么上面的肯定都已经算过了。
这道题相比比第二题是要简单一点的。

原创粉丝点击