• [AT1252] IOIOI カード占い


    前言

    考场上想出( ext{Dijkstra})的是魔鬼吧

    毫无防备地流下了属于真正弱者的泪水.jpg

    题目

    洛谷

    讲解

    所有的 I 被我换成了(1),而 O 换成了(0)

    暴力

    从考场思路开始吧

    首先有显而易见的结论:

    1.选择的操作顺序不影响答案

    2.每个操作重复做没有意义

    好了,这就是我们暴力的基础

    (2^n)枚举操作,判断是否成立,取时间最小值即可

    我是用(bitset)实现的,这里代码就不给出了

    正解

    差分 & 最短路

    区间修改?好难啊! -> 差分!单点修改

    如果当前点和前一个点不一样,取(1),反之取(0)

    如样例可这样变化:

    (100111000011111)

    (010100100010000)

    现在我们只需将所有的(1)改为(0)即可

    上面所对应的(1)的位置为:

    A+1 , A+B+1 , A+B+C+1 , A+B+C+D+1

    由于差分后变为单点修改,那么我们的修改操作也变为了两个点的单点修改

    (u,v)的区间修改变为了(u,v+1)的单点修改

    记上面对应的(1)的位置为(a,b,c,d)

    我们就有三个修改方案:(ab & cd , ac & bd , ad & bc)

    而修改两个点的最小代价就可以用最短路算法( ext{dijkstra})求得

    由于起点只有(a,b,c)三个点,所以我们需要跑三次( ext{dijkstra})

    最后答案取最小值就好了

    坑点

    1. 注意开( ext{long long})

    2. 空间要开(5e5)而非(1e5)

    3. 答案输出要换行! (( ext{AT})老题特性)

    代码

    //12252024832524
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std; 
    
    typedef long long LL;
    const int MAXN = 500005;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    int n,init[6];
    LL dis[3][MAXN],ans = INF;
    struct node
    {
    	int x;
    	LL d;
    	node(){}
    	node(int x1,LL d1){
    		x = x1;
    		d = d1;
    	}
    	bool operator < (const node &px) const{
    		return d >= px.d;
    	}
    };
    
    int Read()
    {
    	int x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    void Put1(LL x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    void Put(LL x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x);
    	if(c >= 0) putchar(c);
    }
    template <typename T>T Max(T x,T y){return x > y ? x : y;}
    template <typename T>T Min(T x,T y){return x < y ? x : y;}
    template <typename T>T Abs(T x){return x < 0 ? -x : x;}
    
    int head[MAXN],tot;
    struct edge
    {
    	int v,val,nxt;
    }e[MAXN << 1];
    void Add_Edge(int x,int y,int z)
    {
    	e[++tot].v = y;
    	e[tot].val = z;
    	e[tot].nxt = head[x];
    	head[x] = tot;
    }
    void Add_Double_Edge(int x,int y,int z)
    {
    	Add_Edge(x,y,z);
    	Add_Edge(y,x,z);
    }
    void dij(int s,LL *DIS)
    {
    	priority_queue<node> q;
    	q.push(node(s,0));
    	DIS[s] = 0;
    	while(!q.empty())
    	{
    		node t = q.top();
    		q.pop();
    		if(t.d > DIS[t.x]) continue;
    		for(int i = head[t.x]; i ;i = e[i].nxt)
    		{
    			if(DIS[e[i].v] > DIS[t.x] + e[i].val) 
    			{
    				DIS[e[i].v] = DIS[t.x] + e[i].val;
    				q.push(node(e[i].v,DIS[e[i].v]));
    			}
    		}
    	}
    }
    
    int main()
    {
    //	freopen("cards.in","r",stdin);
    //	freopen("cards.out","w",stdout);
    	memset(dis,INF,sizeof(dis));
    	for(int i = 1;i <= 5;++ i) init[i] = Read() + init[i-1];
    	n = Read();
    	for(int i = 1,u,v;i <= n;++ i) u = Read(),v = Read(),Add_Double_Edge(u,v+1,v-u+1);
    	dij(init[1]+1,dis[0]);//A
    	dij(init[2]+1,dis[1]);//B
    	dij(init[3]+1,dis[2]);//C
    	ans = Min(ans,dis[0][init[2]+1] + dis[2][init[4]+1]);//AB & CD
    	ans = Min(ans,dis[0][init[3]+1] + dis[1][init[4]+1]);//AC & BD
    	ans = Min(ans,dis[0][init[4]+1] + dis[1][init[3]+1]);//AD & BC
    	if(ans == INF) Put(-1,'
    ');
    	else Put(ans,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    python学习日记——基本数据类型
    python学习日记——安装及初识
    STF平台探索
    fiddler基本操作梳理
    fly.js抛物线连续不断加入购物车
    判断是否存在某个字段hasOwnProperty
    vue中提示toFixed不是函数
    vue中父组件给子组件传值,子组件给父组件传值
    js判断用户的浏览器设备是移动端还是pc端
    css预处理器--sass学习($变量名)
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13392235.html
Copyright © 2020-2023  润新知