题意

    上下有两个位置分别对应的序列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. gitlab使用 —— 多人协同工作(重要技能)

    gitlab使用 —— 多人协同工作(重要技能) 学习链接: http://herry2013git.blog.163.com/blog/static/219568011201341111240751 ...

  2. docker 加速

    Docker配置阿里云加速地址 打开阿里云网站https://cr.console.aliyun.com,登陆自己的阿里云账号. 然后只需要在服务器配置docker配置文件,只需要修改"Ex ...

  3. Mysql储存过程2:变量定义与参数传递

    #储存过程 中的变量定义 declare 变量名 类型 可选类型 -- 跟建表差不多 create procedure p() begin ); ; select age+number; end$ / ...

  4. (转)什么是CDC类(Communication Device Class)

    全文地址:http://justmei.blog.163.com/blog/static/1160998532010321112522467/ 什么是CDC类 (Communication Devic ...

  5. c++各种排序的简单实现

    /* 直插排序 */ void InsertSort(vector<int> &arr){ for(int i = 1;i < arr.size();++i){ for(in ...

  6. gbdt和xgboost中feature importance的获取

    来源于stack overflow,其实就是计算每个特征对于降低特征不纯度的贡献了多少,降低越多的,说明feature越重要 I'll use the sklearn code, as it is g ...

  7. LightOJ 1410 Consistent Verdicts(找规律)

    题目链接:https://vjudge.net/contest/28079#problem/Q 题目大意:题目描述很长很吓人,大概的意思就是有n个坐标代表n个人的位置,每个人听力都是一样的,每人发出一 ...

  8. 20165301 预备作业二:学习基础和C语言基础调查

    <做中学>读后感及C语言学习调查 读<做中学>有感 娄老师在文章中多次提到「做中学(Learning By Doing)」的概念,并通过娄老师自己的减肥经历.五笔练习经历.乒乓 ...

  9. hdu 5692(dfs序+线段树,好题)

    Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  10. ASN.1笔记——语法规则与类型概述

    转载:https://blog.csdn.net/sever2012/article/details/7672699 一.简介 ASN.1(Abstract Syntax Notation doton ...