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

世界上最不缺的就是好题。

首先考虑暴搜。(还有什么题是从这东西推到正解的……)

首先单独一个换乘站明显没用,只用考虑一对对的换乘站。

那么有八种情况:(从题解偷图)

       

然后大力枚举每个换乘站的情况。同时判断交点。$O(n\times 8^{\frac{n}{2}})$。

然后考虑这种情况:

发现对于任意一条地铁线,要么与这两个都有交点,要么可以与这两个都没有交点。(其实会有与一个有两个交点,与另一个没有交点的情况。这时也可以把这条线换个方向,答案不会更差。思考思考为什么)

那么合法状态只剩四种:

   

再考虑这两个线路:

发现,虽然对于左端点在第一个红点右边的地铁线,这两种没有区别,但是对于左端点在第一个红点左边的地铁线,它们可能有区别。
不过由于我们搜索是按左端点从小到大搜的,所以可以贪心取目前这两条线最优的一条,不会影响后面的值。

最后每次合法状态只剩两个。$O(n\times 2^{\frac{n}{2}})$。

此时合法状态不可能再减少了。考虑加速求交点个数。

发现对于左端点小于当前地铁线的左端点的地铁线,与这个地铁线有交点当且仅当右端点在一个区间(具体看代码)内。

那么可以用树状数组优化。每次给右端点打个标记,然后就变成了求区间和。

$O(2^{\frac{n}{2}}\log n)$。

p.s:要调用很多次树状数组,常数也不小,我就挂了,挂成 80 分。

然而加上个普及组剪枝就过了。$sum>ans$ 时 $return$。

(普及组搜索剪枝不会了……智商越来越低了)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=45;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<‘0‘ || ch>‘9‘) f|=ch==‘-‘,ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return f?-x:x;
}
int t,n,m,tp[maxn],l[maxn],r[maxn],ans,sum,b[2][maxn];
inline void update(int id,int p,int v){
    while(p<=n){
        b[id][p]+=v;
        p+=p&-p;
    }
}
inline int query(int id,int p){
    int s=0;
    while(p){
        s+=b[id][p];
        p-=p&-p;
    }
    return s;
}
inline int query(int id,int l,int r){return query(id,r)-query(id,l-1);}
void dfs(int dep){
    if(sum>ans) return;
    if(dep>m) return void(ans=sum);
    int t1=query(0,l[dep],r[dep]),t2=query(0,r[dep],n),t3=query(1,l[dep],r[dep]),t4=query(1,r[dep],n);
    update(0,r[dep],1);
    sum+=min(t1,t2+t3+t4);
    dfs(dep+1);
    sum-=min(t1,t2+t3+t4);
    update(0,r[dep],-1);
    update(1,r[dep],1);
    sum+=min(t3,t1+t2+t4);
    dfs(dep+1);
    sum-=min(t3,t1+t2+t4);
    update(1,r[dep],-1);
}
int main(){
    t=read();
    while(t--){
        m=0;ans=1e9;
        n=read();
        FOR(i,1,n) tp[i]=read();
        FOR(i,1,n) FOR(j,i+1,n) if(tp[i]==tp[j]) l[++m]=i,r[m]=j;
        dfs(1);
        printf("%d\n",ans);
    }
}

原文地址:https://www.cnblogs.com/1000Suns/p/11136145.html

时间: 2024-08-29 21:30:36

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

【清华集训】小Y和地铁

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

BZOJ 3790 神奇项链 Hash+二分+树状数组

题目大意:给定一个串,问这个串最少可以由回文串拼接多少次而成(拼接可以重叠) 首先将每两个字符之间插入占位符,然后Hash+二分搞出所有极大回文串(可以用manacher,我不会) 问题转化成了给定一些区间,求最少的能覆盖整个数轴的区间 将所有区间按照某一端点排序 然后上树状数组即可 回头还是去学学manacher吧... #include <cstdio> #include <cstring> #include <iostream> #include <algo

「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)

学习了新姿势..(一直看不懂大爷的代码卡了好久T T 首先数字范围那么小可以考虑枚举众数来计算答案,设当前枚举到$x$,$s_i$为前$i$个数中$x$的出现次数,则满足$2*s_r-r > 2*s_l-l$的区间$[l+1,r]$其众数为$x$,这个显然可以用一个数据结构来维护. 直接扫一遍效率是$O($数字种类数$*nlogn)$的,无法承受,但是我们发现,对于每一段非$x$的数,$2*s_i-i$是公差为$-1$的等差数列,所以它们对答案的贡献实际上可以一次性计算.设$L$为一段非$x$数

小魂和他的数列-(离散+二分+树状数组)

https://ac.nowcoder.com/acm/problem/54585 题意:给500000个数构成一个数列,求递增个数为k的子序列个数,2<=k<=10. 题解: 1.求递增子序列个数,子序列不是子串,可以散乱分布.原数组为a,排序后为数组b,遍历a数组,每次求得ai在数组b的下标位置,设为pos,在树状数组里对pos位置进行累加,维护k个树状数组,递增个数为j的子序列 需要 递增个数为j-1的子序列的数据.c[i][j]表示的递增个数为i的子序列在j这个位置的个数. 2.一开始

[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

2017.11.26【清华集训2017】模拟

T1 5483. [清华集训2017模拟11.26]简单路径T2 5484. [清华集训2017模拟11.26]快乐树T3 5485. [清华集训2017模拟11.26]字符串 T1 结论题,结论很显然任意两条路径权异或后,会将两条路径的交的贡献删去.然后用个桶存一下出现过的异或和,暴力判一下就可以了 code 1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm

[LOJ#2327]「清华集训 2017」福若格斯

[LOJ#2327]「清华集训 2017」福若格斯 试题描述 小d是4xx9小游戏高手. 有一天,小d发现了一个很经典的小游戏:跳青蛙. 游戏在一个 \(5\) 个格子的棋盘上进行.在游戏的一开始,最左边的两个格子上各有一个向右的青蛙,最右边的两个格子上各有一个向左的青蛙. 每次移动可以选取一个青蛙,向这只青蛙的前方移动一格到空格子中或跳过前方的一个不同朝向的青蛙并移动到空格子中. 为了使你更好地理解这个游戏,我们下发了一个游戏demo作为参考(注意:这个demo中的棋盘大小和题目中并不相同).

[LOJ#2328]「清华集训 2017」避难所

[LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所了." "唔,那你之后会去哪呢?" "去一个没有冬天的地方." 对于一个正整数 \(n\),我们定义他在 \(b\) 进制下,各个位上的数的乘积为 \(p = F(n, b)\). 比如 \(F(3338, 10) = 216\). 考虑这样一个问题,已知 \

[LOJ#2331]「清华集训 2017」某位歌姬的故事

[LOJ#2331]「清华集训 2017」某位歌姬的故事 试题描述 IA是一名会唱歌的女孩子. IOI2018就要来了,IA决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符,第iii个音符的音高为 \(h_i\).IA的音域是 \(A\),她只能唱出 \(1\sim A\) 中的正整数音高.因此 \(1\le h_i\le A\). 在写歌之前,IA需要确定下这首歌的结构,于是她写下了 \(Q\) 条限制,其中第 \(i\) 条为:编号在 \(l_i\) 到 \(r_