题意

    上下有两个位置分别对应的序列A、B,长度为n,两序列为n的一个排列。当Ai == Bj时,上下会连一条边。你可以选择序列A或者序列B进行旋转任意K步,如 3 4 1 5 2 旋转两步为 5 2 3 4 1。求旋转后最小的相交的线段的对数。

  很暴力的就做了这一题,当选择A进行旋转时,A序列翻倍,然后建一棵主席树,记录点Bi的度数,为了更新用(其实可以O(1)更新),然后长度为n的区间扫一遍。

  B亦同。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream> using namespace std; typedef long long LL;
const int maxn = *;
int n, a[maxn], b[maxn], to[maxn];
struct Tree
{
int sum[maxn*], ls[maxn*], rs[maxn*], cnt;
Tree()
{
cnt = ;
}
void pushup(int rt)
{
sum[rt] = sum[ls[rt]]+sum[rs[rt]];
}
void update(int las_rt, int rt, int l, int r, int p, int d)
{
if (l == r)
{
sum[rt] = sum[las_rt]+d;
return ;
}
int mid = (l+r)>>;
if (p <= mid)
{
ls[rt] = ++cnt, rs[rt] = rs[las_rt];
update(ls[las_rt], ls[rt], l, mid, p, d);
}
else
{
ls[rt] = ls[las_rt], rs[rt] = ++cnt;
update(rs[las_rt], rs[rt], mid+, r, p, d);
}
pushup(rt);
}
int query(int rt_1, int rt_2, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return sum[rt_2]-sum[rt_1];
int mid = (l+r)>>, ret = ;
if (L <= mid)
ret += query(ls[rt_1], ls[rt_2], l, mid, L, R);
if (R > mid)
ret += query(rs[rt_1], rs[rt_2], mid+, r, L, R);
return ret;
}
}T1, T2;
int root1[maxn], root2[maxn]; int main()
{
freopen("mincross.in", "r", stdin);
freopen("mincross.out", "w", stdout);
scanf("%d", &n);
for (int i = ; i <= n; ++i)
scanf("%d", &a[i]), a[n+i] = a[i];
for (int i = ; i <= n; ++i)
scanf("%d", &b[i]), b[n+i] = b[i];
//part 1
for (int i = ; i <= n; ++i)
to[b[i]] = i;
root1[] = ++T1.cnt;
T1.update(, root1[], , n, to[a[]], );
for (int i = ; i <= *n; ++i)
{
root1[i] = ++T1.cnt;
T1.update(root1[i-], root1[i], , n, to[a[i]], );
}
LL now_sum = , ans;
for (int i = ; i <= n; ++i)
if (to[a[i]]+ <= n)
now_sum += T1.query(, root1[i], , n, to[a[i]]+, n);
ans = now_sum;
for (int i = n+; i <= *n; ++i)
{
int temp = ;
if (to[a[i]]- >= )
temp = T1.query(root1[i-n], root1[i-], , n, , to[a[i]]-);
now_sum -= temp, now_sum += (n-temp-);
ans = min(ans, now_sum);
}
//part 2
for (int i = ; i <= n; ++i)
to[a[i]] = i;
root2[] = ++T2.cnt;
T2.update(, root2[], , n, to[b[]], );
for (int i = ; i <= *n; ++i)
{
root2[i] = ++T2.cnt;
T2.update(root2[i-], root2[i], , n, to[b[i]], );
}
now_sum = ;
for (int i = ; i <= n; ++i)
if (to[b[i]]+ <= n)
now_sum += T2.query(, root2[i], , n, to[b[i]]+, n);
for (int i = n+; i <= *n; ++i)
{
int temp = ;
if (to[b[i]]- >= )
temp = T2.query(root2[i-n], root2[i-], , n, , to[b[i]]-);
now_sum -= temp, now_sum += (n-temp-);
ans = min(ans, now_sum);
}
cout <<ans <<endl;
return ;
}

USACO 2017 FEB Platinum mincross 可持久化线段树的更多相关文章

  1. USACO 2017 FEB Platinum nocross DP

    题目大意 上下有两个长度为n.位置对应的序列A.B,其中数的范围均为1~n.若abs(A[i]-B[j]) <= 4,则A[i]与B[j]间可以连一条边.现要求在边与边不相交的情况下的最大的连边 ...

  2. LOJ.6073.[2017山东一轮集训Day5]距离(可持久化线段树 树链剖分)

    题目链接 就是恶心人的,简单写写了...(似乎就是[HNOI2015]开店?) 拆式子,记\(dis_i\)为\(i\)到根节点的路径权值和,\(Ans=\sum dis_{p_i}+\sum dis ...

  3. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  4. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  5. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  6. HDU 4866 Shooting(持久化线段树)

    view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...

  7. 【BZOJ-3653】谈笑风生 DFS序 + 可持久化线段树

    3653: 谈笑风生 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 628  Solved: 245[Submit][Status][Discuss] ...

  8. 【BZOJ3673】&&【BZOJ3674】: 可持久化并查集 by zky 可持久化线段树

    没什么好说的. 可持久化线段树,叶子节点存放父亲信息,注意可以规定编号小的为父亲. Q:不是很清楚空间开多大,每次询问父亲操作后修改的节点个数是不确定的.. #include<bits/stdc ...

  9. 【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队

    看到题目就可以想到hash 然后很自然的联想到可持久化权值线段树 WA:base取了偶数 这道题还可以用莫队做,比线段树快一些 可持久化线段树: #include<bits/stdc++.h&g ...

随机推荐

  1. 关于DataTable.Select不到数据的一种解决方案

    网上有很多说的,试过,都没用.自己研究了一下,解决方案如下: 建立dataview,用dv.rowfilter,就可以取到了,然后TOTABLE即可. 代码如下:(只看中间那几句即可) private ...

  2. css预处理scss环境配置

    css 预处理器 CSS 预处理器用一种专门的编程语言,进行 Web css编码,然后再编译成正常的 CSS 文件,以供项目使用:说简单点就是在某个环境下写css 可以写变量.表达式.嵌套等,在通过该 ...

  3. jmeter主要组件

    1.测试计划(Test plan) 2.线程组(Thread Group) 3.配置原件(Configuration) 4.逻辑控制器(Login Controller) 5.取样器(Sampler) ...

  4. 对 makefile 中 .DEFAULT 的理解

    上例子: all:gao @echo "final".DEFAULT: @echo "In default" 由于 gao 是一个前提条件,但是 makefil ...

  5. c#元组举例

    元组的概要: 数组合并了相同类型的对象,而元组合并了不同类型的对象.元组起源于函数编程语言(如F#) ,在 这些语言中频繁使用元组.在N盯4中,元组可通过.NET Fmmework用于所有的NET语言 ...

  6. [VBA]批量替换PPT里的字体颜色

    不知道为什么计组老师的大量课件字体是伤害视力的亮蓝色……看久了眼睛疼,想把颜色替换成保护视力一点的灰色,但是找了N久也没找到在图形界面上直接操作的方法,于是在MSDN上晃了晃,Google了一下,写了 ...

  7. c#中值类型和引用类型的区别

    1.    值类型的数据存储在内存的栈中:引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址. 2.     值类型存取速度快,引用类型存取速度慢. 3.     值类型表示实际数据,引 ...

  8. day5 常用模块json和pickle

    json 和 pickle json和pickle是用于字符串序列化和反序列化的过程,我们在存储和使用的时候,经常把列表存入文件,读取的时候我们还想以列表的形式读取.就需要使用json和pickle. ...

  9. CoreOS 添加用户并赋予sudo权限

    使用root账号登录CoreOS username 为你要添加的用户登录名 添加用户到root组 useradd -g rot username 添加 sudo 权限 visudo -f /etc/s ...

  10. 【C#】线程问题

    多线程编程对很多程序员来说并不容易,在启动访问相同数据的多个线程时,会间歇性地遇到难以发现的问题.如果使用任务.并行LINQ或Parallel类,也会遇到这些问题.为了避免这一系列问题,开发程序中必须 ...