P4005 小 Y 和地铁

题目描述

小 Y 是一个爱好旅行的 OIer。一天,她来到了一个新的城市。由于不熟悉那里的交通系统,她选择了坐地铁。

她发现每条地铁线路可以看成平面上的一条曲线,不同线路的交点处一定会设有

换乘站 。通过调查得知,没有线路是环线,也没有线路与自身相交。任意两条不同的线路只会在若干个点上相交,没有重合的部分,且没有三线共点的情况。即,如图所示的情况都是不存在的:

小 Y 坐着地铁 0 号线,路上依次经过了 n 个换乘站。她记下了每个换乘站可以换乘的线路编号,发现每条线路与她所乘坐的线路最多只有 2 个换乘站。现在小 Y 想知道,除掉她经过的换乘站以外,这个城市里最少有几个换乘站。只有你告诉她正确的答案,她才会答应下次带你去玩呢。

输入输出格式

输入格式:

从文件 metro.in 中读入数据。

请.注.意.本.题.有.多.组.输.入.数.据。

输入数据的第一行是一个整数 T,表示输入数据的组数。接下来依次给出每组数据。

对于每组数据,第一行是一个整数 n,表示小 Y 经过的换乘站的数目。第二行为 n个用空格隔开的整数,依次表示每个换乘站的可以换乘的线路编号。这些编号都在 1 ~n 之内。

输出格式:

输出到文件 metro.out 中。

对于每组输入数据,输出一行一个整数,表示除掉这 n 个换乘站之外,最少有几个换乘站。

输入输出样例

输入样例#1:

4 4
1 2 1 2
8
1 2 3 4 1 2 3 4
5
5 4 3 3 5
8
1 2 3 4 1 3 2 4

输出样例#1:

0
0
0
1

说明

【样例 1 解释】

对于样例的前两组数据,一种可能的最优答案如下图所示。

【子任务】

一共有 50 个测试点,每个测试点 2 分。你只有在答案完全正确时才能得到该测试点的全部分数,否则不得分。

对于所有测试点,以及对于样例, 1 ≤ T ≤ 100; 1 ≤ n ≤ 44。对于每个测试点, n 的范围如下表:

Solution:

  本题ZYYS,绝世搜索好题。

  题意有些晦涩,总结后不难发现实际路线只有$4$种情况:

     

               

  至于洛谷题解中的开始8种情况的另外4种,贪心的想到,完全没有必要那样建,比如:

  

  由于要使各曲线的交点尽量少,那么上面两幅图肯定是没有这幅图优秀的:

  然后在最上面说的4种情形中,由于上部的曲线不可能和下部的曲线相交,所以可以将其上下分开看,而既有上部又有下部的图直接将其当作两个部分的曲线合并,比如:

理解为上部的曲线$[l,n]$+下部的曲线$[r,n]$就好了。

  然后对于同上或同下的两个曲线$[l1,r1],[l2,r2]$,显然只有$l2\leq r1\leq r2$时才会有交点,那么计算一段曲线会产生多少交点,就得统计区间$[l,r]$之间的已有$r$个数,单点修改区间查询直接想到树状数组。

  这样就能直接暴力搜索,枚举每条曲线的形态,对于既有上部和下部的曲线,发现可以和另一条单部曲线合并成环,比如:从左到右枚举曲线状态,当前状态只受左边的影响,由于$l$左边的状态已确定,而$r$是确定的,所以当前$[l,r]$的最优情况直接贪心选择两种方式的与左边交点的最小个数就好了,另一种情况同理就好了。

  时间复杂度$O(2^{\frac{n}{2}}\log n)$。

代码:

/*Code by 520 -- 9.2*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=100;
int n,a[N],T,l[N],r[N],ans,num;
struct node{
    int c[N];
    void clear(){memset(c,0,sizeof(c));}
    void add(int x,int k){while(x<=n)c[x]+=k,x+=x&-x;}
    int sum(int x){int ans=0;while(x)ans+=c[x],x-=x&-x;return ans;}
    int query(int l,int r){return sum(r)-sum(l-1);}
}up,down;

int gi(){
    int a=0;char x=getchar();
    while(x<‘0‘||x>‘9‘)x=getchar();
    while(x>=‘0‘&&x<=‘9‘)a=(a<<3)+(a<<1)+(x^48),x=getchar();
    return a;
}

void dfs(int x,int tot){
    if(x>num){ans=min(ans,tot);return;}
    if(tot>=ans)return;
    int upp=min(up.query(l[x],r[x]),down.query(l[x],n)+up.query(r[x],n));
    up.add(r[x],1),dfs(x+1,tot+upp),up.add(r[x],-1);
    int downn=min(down.query(l[x],r[x]),up.query(l[x],n)+down.query(r[x],n));
    down.add(r[x],1),dfs(x+1,tot+downn),down.add(r[x],-1);
}

il void solve(){
    for(T=gi();T;--T){
        scanf("%d",&n),ans=0x7fffffff,num=0;
        For(i,1,n) a[i]=gi();
        For(i,1,n) For(j,i+1,n) if(a[i]==a[j]){l[++num]=i,r[num]=j;break;}
        up.clear(),down.clear();
        dfs(1,0);
        printf("%d\n",ans);
    }
}

int main(){
    solve();
    return 0;
}

原文地址:https://www.cnblogs.com/five20/p/9575716.html

时间: 2024-10-08 01:16:36

P4005 小 Y 和地铁的相关文章

【清华集训】小Y和地铁

题目: 小 $\rm Y$ 是一个爱好旅行的 $\rm OIer$.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁.她发现每条地铁线路可以看成平面上的一条曲线,不同线路的交点处一定会设有换乘站.通过调查得知,没有线路是环线,也没有线路与自身相交.任意两条不同的线路只会在若干个点上相交,没有重合的部分,且没有三线共点的情况.即,如图所示的情况都是不存在的: 小 Y 坐着地铁 $0$ 号线,路上依次经过了 $n$ 个换乘站.她记下了每个换乘站可以换乘的线路编号,发现每条线路与她

[清华集训2017]小 Y 和地铁(神奇思路,搜索,剪枝,树状数组)

世界上最不缺的就是好题. 首先考虑暴搜.(还有什么题是从这东西推到正解的……) 首先单独一个换乘站明显没用,只用考虑一对对的换乘站. 那么有八种情况:(从题解偷图)         然后大力枚举每个换乘站的情况.同时判断交点.$O(n\times 8^{\frac{n}{2}})$. 然后考虑这种情况: 发现对于任意一条地铁线,要么与这两个都有交点,要么可以与这两个都没有交点.(其实会有与一个有两个交点,与另一个没有交点的情况.这时也可以把这条线换个方向,答案不会更差.思考思考为什么) 那么合法

2469: 小Y的难题1---SWUST 信息学院OJ

题目描述:http://www.oj.swust.edu.cn/problem/show/2469 Description 最近小Y迷上了数学,总是在思考各种数学问题.有一天,他不小心把墨水洒在草稿纸上.他现在能看到的是“2?3?1?4”(?表示看不清的地方).小Y的记忆力不错,他知道: 1.每个?只会是“+”.“-”,“=”三个符号之一. 2.总共有且仅有一个“=”. 3.原式一定是一个等式.如“2+3-1=4” 现在他突然想知道,有多少种可能性,满足上面3个要求. Input 多组输入. 每

小Y的难题

Font Size:Aa Aa Aa Description 近期小Y迷上了数学,总是在思考各种数学问题. 有一天,他不小心把墨水洒在草稿纸上.他如今能看到的是"2?3?1? 4"(?表示看不清的地方).小Y的记忆力不错,他知道: 1.每一个?仅仅会是"+"."-"."="三个符号之中的一个. 2.总共同拥有且仅有一个"=". 3.原式一定是一个等式.如"2+3-1=4" 如今他突然想知

小Y的轮回之路——攒机装机、B150装win7

两个月前,陪伴我5年多的小Y(ideapad-y460N卡)突然大伤元气,硬盘跪了,显示屏也黑了一小块.本着经济实惠凑合用的态度换了个320G的硬盘,没想过几天显示屏情况加重,出现无数个红绿相间的线条.正所谓天下无不散之筵席,既然无缘并肩作战,那就一路走好~ 寻寻觅觅,冷冷清清,凄凄惨惨戚戚.在无数次寻寻觅觅后,决定入手一款台式机.记得小时候有一阵子特别时兴组装机,奈何当时不太懂电脑各种乱七八糟的参数,买的都是品牌机.现在也懂个七七八八了,反正都是套路嘛!既然有需求,有情怀,又有知识,那就搞起吧

[LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主

[LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主 试题描述 "A fight? Count me in!" 要打架了,算我一个. "Everyone, get in here!" 所有人,都过来! 小Y是一个喜欢玩游戏的OIer.一天,她正在玩一款游戏,要打一个Boss. 虽然这个Boss有 \(10^{100}\) 点生命值,但它只带了一个随从--一个只有 \(m\) 点生命值的"恐怖的奴隶主". 这个"恐怖的奴隶主&qu

UOJ#339. 【清华集训2017】小 Y 和二叉树 贪心

原文链接 www.cnblogs.com/zhouzhendong/p/UOJ339.html 前言 好久没更博客了,前来更一发. 题解 首先,我们考虑一个子问题:给定根,求出最小中序遍历. 如果根节点有一个儿子,那么,我们需要比较根节点和 儿子的最小中序遍历的第一个元素,选择较优的一方放在前面. 如果根节点有两个儿子,那么,我们必然选择最小中序遍历较小的儿子放在左儿子. 由于所有节点编号互不相同,所以我们在比较两个部分的字典序时,只关注第一个元素的大小. 可以发现,一个有两个儿子的节点是不可能

小Y的涂鸦 数学期望 dp

题意概述: 现在给出一个N*N的方格纸,有M个格子已经被涂黑了.现在小明也来涂格子,每次等概率地涂格子(包括已经被涂过的),问期望的涂格子次数,使得方格纸每一行每一列都至少有一个格子被涂过. 数据范围: 1 ≤ n ≤ 2·103,0 ≤ m ≤ min(n2, 2·103),1 ≤ ri, ci ≤ n  (这是给出的涂过的格子的坐标), Time limit : 1 s,Memory limit : 512 mb 分析: 我开始有一点小小的认为我的脑子可能有点好使了(YY出一个自己认为掌握的

小Y的Python学习日志--流程控制(逻辑符)

#本文仅为个人学习过程的整理和记录,如有从他人博客.网站摘录的内容,本人会明确标明,如有涉及侵权,请联系本人,本人会在第一时间删除.  以下的资料整理来自(1)廖雪峰的Python教程 http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000 (2)简明Python教程 http://woodpecker.org.cn/abyteofpython_cn/chinese/ (1)逻辑运算符