Codeforces Round #248 (Div. 2) C - Ryouko's Memory Note

题意

一本书有n页。下面要找m个知识点,分别在s[1] s[2]….s[m]页上。

现在有一个机会,可以把某一页的知识点全部移到另一页上。求最少的翻页次数。

如s[1] s[2] …. s[m]的翻页次数就是|s[1]-s[2]|+|s[2]-s[3]|+…+|s[m-1]-s[m]|

思路

记录每个页码在序列中前后出现的页码(如1 2 3 2 4 则2前后出现过1 3 3 4)(注意如果相邻的页码相同则不用管它) 取它们的中位数,这时一定会有移动这个页码的最优解。把所有页码遍历一遍,取整体最优解即可。

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iostream>
#define ll long long
using namespace std;
const int maxn = 100010;
const ll INF = 1e10L;
int s[maxn];
vector<int> ss[maxn];
ll close[maxn];
ll closee[maxn];
ll sum;
ll ans;
int ma;
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1 ; i <= m ; i ++) {
        scanf("%d",&s[i]);
        ma = max(ma,s[i]);
        if(i != 1) {
            sum += abs(s[i]-s[i-1]);
            if(s[i] == s[i-1]) continue;
            ss[s[i]].push_back(s[i-1]);
            ss[s[i-1]].push_back(s[i]);
            close[s[i]] += abs(s[i]-s[i-1]);
            close[s[i-1]] += abs(s[i]-s[i-1]);
        }
    }
    ans = sum;
    for(int i = 1 ; i <= ma ; i ++) {
        if(!ss[i].size()) continue;
        sort(ss[i].begin(),ss[i].end());
        int mid = ss[i].size()/2;
        for(int j = 0 ; j < ss[i].size() ; j ++) {
            closee[i] += abs(ss[i][j]-ss[i][mid]);
        }
        ans = min(ans,sum-close[i]+closee[i]);
    }
    cout << ans << endl;
    return 0;
}

Codeforces Round #248 (Div. 2) C - Ryouko's Memory Note

时间: 2024-10-10 23:31:09

Codeforces Round #248 (Div. 2) C - Ryouko's Memory Note的相关文章

Codeforces Round #248 (Div. 1)——Ryouko&#39;s Memory Note

题目连接 题意: 给n和m,一行m个1<=x<=n的数.记c=.现在只能选择一个数x变成y,序列中所有等于x的值都变成y,求最小的c 分析: 对于一个数x,把与他相邻的所有的非x的数全部写下来.如果x增大,那么一部分值增大,一部分减小,且每个数的增大值或减小值都是x的变化值(均相等),也就是说总的结果只和比x大的数与比x小的数的数量有关,所以即中位数. const int maxn = 110000; LL ipt[maxn]; map<LL, vector<LL> >

Codeforces Round #248 (Div. 1)——Nanami&amp;#39;s Digital Board

题目连接 题意: 给n*m的0/1矩阵,q次操作,每次有两种:1)将x,y位置值翻转 2)计算以(x,y)为边界的矩形的面积最大值 (1?≤?n,?m,?q?≤?1000) 分析: 考虑以(x,y)为下边界的情况,h=(x,y)上边最多的连续1的个数.那么递减的枚举,对于当前hx,仅仅须要看两側能到达的最远距离,使得h(x,ty)不大于h就可以.之后的枚举得到的两側距离大于等于之前的,所以继续之前的两側距离继续枚举就可以. const int maxn = 1100; int n, m, q;

Codeforces Round #248 (Div. 2) A - Kitahara Haruki&#39;s Gift

题意 给n个数,都是100或者200,问能否把这些数平均分给两个人. 思路 先算出如果平均分的话每个人要多少(sum/2),如果不能整除100那么肯定不行.如果是100的倍数,则先尽量用200的,用完200的或者已经不足200了再用100的. 代码 #include <cstdio> #include <algorithm> using namespace std; const int maxn = 110; int s[maxn]; int n; int main() { int

Codeforces Round #248 (Div. 2) B - Kuriyama Mirai&#39;s Stones

题意 给出一个n个数的序列.下面有m个指令 1指令:原序列从l到r的和 2指令:排序过的序列从l到r的和 思路 线段树可做-.直接扫一遍记录sum数组也可以 代码 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define ll long long const int maxn = 100010; int n; int s[maxn]; int ss[max

Codeforces Round #248 (Div. 1)——Nanami&#39;s Digital Board

题目连接 题意: 给n*m的0/1矩阵,q次操作,每次有两种:1)将x,y位置值翻转 2)计算以(x,y)为边界的矩形的面积最大值 (1?≤?n,?m,?q?≤?1000) 分析: 考虑以(x,y)为下边界的情况,h=(x,y)上边最多的连续1的个数.那么递减的枚举,对于当前hx,只需要看两侧能到达的最远距离,使得h(x,ty)不大于h即可.之后的枚举得到的两侧距离大于等于之前的,所以继续之前的两侧距离继续枚举即可. const int maxn = 1100; int n, m, q; int

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/

Codeforces Round 239 Div 1

都怪自己太懒了 这段时间比赛参加了大部分,但是一直都没写题解,趁这几天没事,计划把这段时间的题解都补上. 上一次比赛(248)终于升到了div1,所以从这次开始就开始写div1了. A. Triangle There is a right triangle with legs of length a and b. Your task is to determine whether it is possible to locate the triangle on the plane in such

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿