[APIO/ctsc2007]

A.风铃

给一棵二叉树,叶子结点是玩具,为使你的弟弟满意,你需要选一个满足下面两个条件的风铃:

(1) 所有的玩具都在同一层(也就是说,每个玩具到天花板之间的杆的个数是一样的)或至多相差一层。
(2) 对于两个相差一层的玩具,左边的玩具比右边的玩具要更靠下一点。

你可以交换一个非叶子节点的左右孩子,问至少要交换多少次可以满足或者输出无解。 非叶子节点不超过100000个

题解:题目的限制条件很多,因此很多情况都是无解的,都特判一下。

以下代码卡时间卡空间卡到bzojRank1了

#include<iostream>
#include<cstdio>
#define getchar() (*S++)
#define pa pair<int,int>
#define mk(x) make_pair(x,x)
#define mp(x,y) make_pair(x,y)
#define MN 100000
using namespace std;
char B[1<<23],*S=B;
inline int read()
{
    int x = 0; char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘){ if(ch == ‘-‘){getchar();return -1;} ch = getchar();}
    while(ch >= ‘0‘ && ch <= ‘9‘){x =(x<<1)+(x<<3) + ch - ‘0‘;ch = getchar();}
    return x;
}
int rt,n,flag=0,ans=0;
int c[MN+1][2],dep[MN+1];
bool mark[MN+1],yes=true;
inline int abs(int x){return x<0?-x:x;}
inline int max(int x,int y){return x<y?y:x;}
inline int min(int x,int y){return x<y?x:y;}

pa dfs(int x)
{
    if(flag>1)return mp(0,0);
    if(min(c[x][0],c[x][1])==-1&&max(c[x][0],c[x][1])!=-1) ++flag;
    pa dp1,dp2;
    if(c[x][0]==-1) dp1=mk(dep[x]+1); else dep[c[x][0]]=dep[x]+1,dp1=dfs(c[x][0]);
    if(c[x][1]==-1) dp2=mk(dep[x]+1); else dep[c[x][1]]=dep[x]+1,dp2=dfs(c[x][1]);
    int mn=min(dp1.first,dp2.first),mx=max(dp1.second,dp2.second);
    if(abs(mx-mn)>1||(dp1.first!=dp1.second&&dp2.first!=dp2.second)) flag=3;
    if(dp1.first<dp2.second)ans++;
    return mp(mn,mx);
}

int main()
{
    fread(B,1,1<<23,stdin);
    n=read();
    for(register int i=1;i<=n;i++)
    {
        c[i][0]=read();c[i][1]=read();
        if(c[i][0]!=-1) mark[c[i][0]]=1;
        if(c[i][1]!=-1) mark[c[i][1]]=1;
    }
    for(rt=1;mark[rt];++rt);
    dfs(rt);
    if(flag>1) return 0*puts("-1");
    printf("%d\n",ans);
    return 0;
}

B.数据备份

给定一条直线上n个点,你要两两配出k对,每个点最多只能在一对内,求最小的每队的距离之和。 n<=100000,x<=10^9

题解:这题真的妙......

我们先把每条线段都扔到一个堆里面,然后每次取出堆顶最小的那条线段,假设是连续的四个点a b c d中的bc段,那么我让答案加上bc段之后,加入ab+cd-bc这一段,删去ab和cd两段,取出k次之后,就能得到最优解。

为什么呢:加入你ab,cd只选一段,那么把它换成bc一定更优。假如你两段都不选,那么我把一段更小的换成bc也一定更优。如果你两段都选,没问题,你选择我新加的这一段,bc已经被扣除了,满足条件。  复杂度是nlogn的。

这个其实就类似网络流的退流操作。

#include<iostream>
#include<cstdio>
#include<queue>
#define INF 2000000000
#define MN 100000
#define pa pair<long long,int>
#define mp make_pair
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}

long long ans=0;
int n,k,ne[MN+5],la[MN+5],a[MN+5],len[MN+5];
bool del[MN+5];
priority_queue<pa,vector<pa>,greater<pa> > q;

int main()
{
    n=read();k=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n+1;i++)la[i+1]=i,ne[i]=i+1;
    la[1]=0;ne[n+1]=0;
    for(int i=2;i<=n;i++)
        q.push(mp(len[i]=a[i]-a[i-1],i));
    len[1]=len[n+1]=INF;
    for(int i=1;i<=k;i++)
    {
        while(del[q.top().second])q.pop();
        ans+=q.top().first;int x=q.top().second;q.pop();
        int a=la[x],b=ne[x];
        del[a]=del[b]=1;
        q.push(mp(len[x]=len[a]+len[b]-len[x],x));
        la[x]=la[a];ne[x]=ne[b];
        ne[la[a]]=x;la[ne[b]]=x;
    }
    cout<<ans;
    return 0;
}

C.动物园zoo

从前有座动物园,那里的动物围成圈。有n个动物,m个小朋友(n<=10000,m<=50000),每个小朋友可以看到连续的5只动物,有自己喜欢的和讨厌的。你现在要移走一些动物,一个小朋友会高兴当有一只她喜欢的动物没被移走或者有一只它讨厌的动物被移走了。求最多可以让几个小朋友高兴。

题解:一开始想到什么最小割之类的.....然而并不是。正解壮压dp,用f[i][j]表示前i只动物,最后五只动物的移动情况为j,最多能使几个小朋友高兴,然后就很容易转移啦。

但是这里的动物是围成圈的,可以暴力枚举前四个动物。复杂度$O(n*2^{9}+2^{4}*m)$

位运算真牛逼真好用

#include<iostream>
#include<cstdio>
#include<cstring>
#define INF 2000000000
#define MN 10000
#define MP 50000
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}

unsigned int love[MP+5],hate[MP+5];
int f[MN+5][35],n,c,ans=0,pos[MP+5];

void solve(int pre)
{
    int k=1;
    for(int i=5;i<=n;i++)
    {
        int m=k;
        for(unsigned int j=0;j<16;j++)
        {
            int last=max(f[i-1][j+16],f[i-1][j]);
            int ad1=0,ad2=0;unsigned int th=j<<1;
            for(k=m;k<=c&&pos[k]==i;k++)
            {
                if((th&love[k])>0||((~th)&hate[k])>0) ad1++;
                if(((th+1)&love[k])>0||((~(th+1))&hate[k])>0) ad2++;
            }
            f[i][th]=max(f[i][th],last+ad1);
            f[i][th+1]=max(f[i][th+1],last+ad2);
        }
    }
    int j=pre,m=k;
    for(unsigned int i=0;i<32;i++)
        {
            int ad=0;
            for(k=m;k<=c;k++)
            {
                int a=(pos[k]-n);
                unsigned int num=((i-((i>>(5-a))<<(5-a)))<<a)+(j>>(4-a));
                if((love[k]&num)>0||((~num)&hate[k])>0) ad++;
            }
            ans=max(ans,f[n][i]+ad);
        }
}

void work()
{
    for(int num=0;num<16;num++)
    {
        memset(f,0,sizeof(f));
        for(int i=0;i<32;i++)f[4][i]=-INF;f[4][num]=0;
        solve(num);
    }
}

int main()
{
    n=read();c=read();
    for(int i=1;i<=c;i++)
    {
        pos[i]=read();
        int num1=read(),num2=read();
        for(int j=1;j<=num1;j++)
            love[i]|=1<<(4-((read()+n-pos[i])%n));
        for(int j=1;j<=num2;j++)
            hate[i]|=1<<(4-((read()+n-pos[i])%n));
        pos[i]+=4;
    }
    work();
    printf("%d\n",ans);
    return 0;
}
时间: 2024-10-12 07:37:36

[APIO/ctsc2007]的相关文章

【BZOJ 1177】【APIO 2009】Oil

http://www.lydsy.com/JudgeOnline/problem.php?id=1177 前缀和优化,时间复杂度$O(nm)$ 因为数据不全,快速读入会导致RE,切记! #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1503; int in() { int k = 0, fh = 1; char c = getchar()

[bzoj 1911][Apio 2010]特别行动队(斜率优化DP)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1911 分析: 首先可以的到裸的方程f[i]=max{f[j]+a*(Si-Sj)^2+b*(Si-Sj)+c} 0<j<i 简化一下方程,我们知道对于一次项,最后结果肯定是b*Sn 所以可以写成f[i]=max{f[j]+a*(Si-Sj)^2+c} 0<j<i 我们不妨设0<x<y<i,且x比y优 即f[x]+a*(Si-Sx)^2+c>f[y]+a*

APIO启示录

卡线. 真没想到会在这么奇葩的位置,不过考都考完了,还能有什么办法呢. 这次考得分数也实在是奇葩,前两题拿分都低于平均分,却过了第三题. 她说得也对,不是水平的问题,是心态的问题. 连续两次这样了,考试的时候整个人脑子一团乱麻,整个人都神经兮兮的. 不知是为什么,练太少?太紧张? 希望下次能考好些吧.BA APIO启示录,布布扣,bubuko.com

【链表】bzoj 1150: [CTSC2007]数据备份Backup

1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1136  Solved: 458[Submit][Status][Discuss] Description Input 输入的第一行包含整数n和k,其中n(2 ≤ n ≤100 000)表示办公楼的数目,k(1≤ k≤ n/2)表示可利用的网络电缆的数目.接下来的n行每行仅包含一个整数(0≤ s ≤1000 000 000), 表示每个办公楼到大

【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列)

1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣.已知办公 楼都位于同一条街上.你决定给这些办公楼配对(两个一组).每一对办公楼可以通过在这两个建筑物之间铺设网 络电缆使得它们可以互相备份.然而,网络电缆的费用很高.当地电信公司仅能为你提供 K 条网络电缆,这意味 着你仅

CTSC &amp;&amp; APIO 行程记录

CTSC: 第一天,看着三道题,只觉得第三题可做.于是写了第一题的暴力就开始写第三题的题答,第二题看了萨菲克斯阿瑞的名字就感觉不会写呀.然而第三题只能胡搞乱搞就只有28分. D1 5 + 0 + 28 = 33 第二天,看了看第一题:30分不是SB题吗?于是开始写,后来发现不会构造偶数阶的那个啥矩阵....出来以后才发现自己写的30分是50分的.第三题一个DFS跑3h水出了40分. D2 50+0+40 = 90 SUM 33 + 90 = 123 颁奖那天,尴尬的事情发生了:Ag线125...

GDOI 2016 &amp; APIO 2016 游记

缓慢施工中...... 今年apio竟然没和gdoi撞...智障选手多了一个旅游机会233 GDOI2016游记 day0 坐动车到广州,然后坐了两三个小时的大巴+公交车才到四会......我之前一直以为偏远小渔村是全省最落后的城市QAQ KPM:“我是来旅游的”..结果被我们奶成了tourist233 酒店倒是挺新的...然而附近什么都没有啊喂..吃个饭都得坐半小时的大巴去四会中学的食堂... 食堂做的菜似乎不是很好吃= = 喜闻乐见地没带笔记本的充电线TAT.....(强行攒满RP...只好

CTSC &amp;&amp; APIO 总结

先说CTSC吧,第一试其实不难但是下意识觉得CTSC不就只能骗分吗,然后就全上暴力了.然而第二题再一次看漏了条件,即答案总和小于等于1e6.第三题现在回想起来要不然就是没有思考,要不然就是没学过数学,居然两圆相交用勾股定理都没想到. 第二试没听评讲,但是khb A掉了第一题,说明其实第二试是可做的.具体细节只有下来再说了. 然后是APIO,虽然考的不错但是居然我是考场上唯一一个只没有做出第一题的人.顺便说一句,第二三题基本都是乱搞水过,还是感谢不会spfa的外国出题者门.... APIO的讲课确

CTSC+APIO+THUACM游记

退役之前,写点破事乐呵乐呵.. (同DaD3zZ) CTSC Day0 来到丽都 哈哈哈这可是四星级豪华酒店啊   想想要在这住7天  美滋滋 换了半天的房间 也没有换到一起   最后yzy&gzz两位大佬(THU和PKU一本大爷)去了珀利 打开屋子 woc? 大床房  Excuse me ? ............看我无语的表情  = = 晚上跟lty睡到了一张床(雾) Day1 进考场之前跟lty&ysq谈笑风生 lty奶了自己一口:AK! 开场5min T1 30pts随便写吧 T