hdu 6375 度度熊学队列 (链表模拟)

度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣。

初始时有 N 个空的双端队列(编号为 1 到 N ),你要支持度度熊的 Q 次操作。

①1 u w val 在编号为 u 的队列里加入一个权值为 val 的元素。(w=0 表示加在最前面,w=1 表示加在最后面)。

②2 u w 询问编号为 u 的队列里的某个元素并删除它。( w=0 表示询问并操作最前面的元素,w=1 表示最后面)

③3 u v w 把编号为 v 的队列“接在”编号为 u 的队列的最后面。w=0 表示顺序接(队列 v 的开头和队列 u 的结尾连在一起,队列v 的结尾作为新队列的结尾), w=1 表示逆序接(先将队列 v 翻转,再顺序接在队列 u 后面)。且该操作完成后,队列 v 被清空。

维护双向链表模拟, 删除的时候要注意判断删除后的结点在哪一侧.

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl ‘\n‘
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<‘ ‘;hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<‘0‘||p>‘9‘)p=getchar();while(p>=‘0‘&&p<=‘9‘)x=x*10+p-‘0‘,p=getchar();return x;}
//head

const int N = 1e7+10;
int n, q, clk;
int head[N], tail[N];
struct _ {int l,r,v;} a[N];
int tim[N],ti;
void upd(int x) {
    if (tim[x]!=ti) tim[x]=ti,head[x]=tail[x]=0;
}
void addL(int id, int v) {
    upd(id);
    a[++clk].v = v;
    if (!head[id]) {
        head[id] = tail[id] = clk;
        a[clk].l = a[clk].r = -1;
    }
    else {
        if (a[head[id]].l==-1) {
            a[head[id]].l = clk;
            a[clk].l = -1;
            a[clk].r = head[id];
        }
        else {
            a[head[id]].r = clk;
            a[clk].r = -1;
            a[clk].l = head[id];
        }
        head[id] = clk;
    }
}
void addR(int id, int v) {
    upd(id);
    a[++clk].v = v;
    if (!tail[id]) {
        head[id] = tail[id] = clk;
        a[clk].l = a[clk].r = -1;
    }
    else {
        if (a[tail[id]].l==-1) {
            a[tail[id]].l = clk;
            a[clk].l = -1;
            a[clk].r = tail[id];
        }
        else {
            a[tail[id]].r = clk;
            a[clk].r = -1;
            a[clk].l = tail[id];
        }
        tail[id] = clk;
    }
}
void delL(int id) {
    upd(id);
    if (!head[id]) return puts("-1"),void();
    printf("%d\n", a[head[id]].v);
    if (a[head[id]].l==-1&&a[head[id]].r==-1) {
        head[id] = tail[id] = 0;
		return;
    }
	int t = head[id];
	if (a[t].l==-1) head[id] = a[t].r;
	else head[id] = a[t].l;
	if (a[head[id]].r==t) a[head[id]].r = -1;
	else a[head[id]].l = -1;
}
void delR(int id) {
    upd(id);
    if (!tail[id]) return puts("-1"),void();
    printf("%d\n", a[tail[id]].v);
    if (a[tail[id]].l==-1&&a[tail[id]].r==-1) {
        head[id] = tail[id] = 0;
		return;
    }
	int t = tail[id];
    if (a[t].l==-1) tail[id] = a[t].r;
	else tail[id] = a[t].l;
	if (a[tail[id]].l==t) a[tail[id]].l = -1;
	else a[tail[id]].r = -1;
}
void reverse(int id) {
    upd(id);
    swap(head[id],tail[id]);
}
void merge(int x, int y) {
    if (x==y) return;
    upd(x),upd(y);
    if (!head[y]) return;
    if (!head[x]) {
        head[x] = head[y];
        tail[x] = tail[y];
    }
    else {
        if (a[tail[x]].l==-1) a[tail[x]].l = head[y];
        else a[tail[x]].r = head[y];
        if (a[head[y]].l==-1) a[head[y]].l = tail[x];
        else a[head[y]].r = tail[x];
        tail[x] = tail[y];
    }
    head[y] = tail[y] = 0;
}

void read(int &x){
    scanf("%d",&x);
}

int main() {
    while (~scanf("%d%d", &n, &q)) {
        ++ti;
        while (q--) {
            int op,u,v,w;
            read(op),read(u),read(v);
            if (op==1) {
                read(w);
                if (v==0) addL(u,w);
                else addR(u,w);
            }
            else if (op==2) {
                if (v==0) delL(u);
                else delR(u);
            }
            else {
                read(w);
                if (w) reverse(v);
                merge(u,v);
            }
        }
    }
}

原文地址:https://www.cnblogs.com/uid001/p/11139806.html

时间: 2024-10-14 09:04:10

hdu 6375 度度熊学队列 (链表模拟)的相关文章

度度熊学队列

ps:模拟为啥能过....写vector<deque<int> > mq会超内存,改成map<int, deque<int> > mq能行,why? /* 合并两个队列 */if (w == 0) { mq[u].insert(mq[u].end(), mq[v].begin(), mq[v].end()); mq[v].clear(); } else { mq[u].insert(mq[u].end(), mq[v].rbegin(), mq[v].ren

【2018百度之星初赛(A)】1002 度度熊学队列

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6375 Knowledge Point: STL - map:https://www.cnblogs.com/liubilan/p/9458765.html STL - deque:https://www.cnblogs.com/liubilan/p/9461141.html 这道题主要考的是STL容器的使用,没有写出来只说明了一个道理: STL很重要啊!目前你用到的没用到的你都得了解并且会使用啊!!

2018 “百度之星”程序设计大赛 - 初赛(A)度度熊学队列 list rope

c++ list使用 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #include <set> 8 #include <map> 9 #include <list> 10 #include <e

hdu 6118 度度熊的交易计划(可行费用流)

题目链接:hdu 6118 度度熊的交易计划 题意: 中文,说的很清楚了. 题解: 对着输入建一些图,跑一下可行费用流就行了,即当费用为正的时候就不跑了,这样就先满足了费用最小. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 namespace MCMF 6 { 7 const int N=1e5+7,inf=1e9+7; 8 int u[

【判连通】HDU 6113 度度熊的01世界

http://acm.hdu.edu.cn/showproblem.php?pid=6113 [题意] 度度熊是一个喜欢计算机的孩子,在计算机的世界中,所有事物实际上都只由0和1组成. 现在给你一个n*m的图像,你需要分辨他究竟是0,还是1,或者两者均不是. 图像0的定义:存在1字符且1字符只能是由一个连通块组成,存在且仅存在一个由0字符组成的连通块完全被1所包围. 图像1的定义:存在1字符且1字符只能是由一个连通块组成,不存在任何0字符组成的连通块被1所完全包围. 连通的含义是,只要连续两个方

HDU 6113 度度熊的01世界 【DFS】(2017&quot;百度之星&quot;程序设计大赛 - 初赛(A))

度度熊的01世界 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1117    Accepted Submission(s): 400 Problem Description 度度熊是一个喜欢计算机的孩子,在计算机的世界中,所有事物实际上都只由0和1组成. 现在给你一个n*m的图像,你需要分辨他究竟是0,还是1,或者两者均不是. 图像0

HDU 6113 度度熊的01世界

度度熊的01世界 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1276    Accepted Submission(s): 466 Problem Description 度度熊是一个喜欢计算机的孩子,在计算机的世界中,所有事物实际上都只由0和1组成. 现在给你一个n*m的图像,你需要分辨他究竟是0,还是1,或者两者均不是. 图像0

hdu 6082 度度熊与邪恶大魔王(2017&quot;百度之星&quot;程序设计大赛 - 资格赛 )

度度熊与邪恶大魔王 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 251    Accepted Submission(s): 125 Problem Description 度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来.邪恶大魔王的麾下有n个怪兽,每个怪兽有a[i]的生命值,以及b[i]的防御力.度度熊一共拥有m种攻击方式,第i

HDU - 6082 度度熊与邪恶大魔王(背包变式)

度度熊与邪恶大魔王 度度熊为了拯救可爱的公主,于是与邪恶大魔王战斗起来. 邪恶大魔王的麾下有n个怪兽,每个怪兽有a[i]的生命值,以及b[i]的防御力. 度度熊一共拥有m种攻击方式,第i种攻击方式,需要消耗k[i]的晶石,造成p[i]点伤害. 当然,如果度度熊使用第i个技能打在第j个怪兽上面的话,会使得第j个怪兽的生命值减少p[i]-b[j],当然如果伤害小于防御,那么攻击就不会奏效. 如果怪兽的生命值降为0或以下,那么怪兽就会被消灭. 当然每个技能都可以使用无限次. 请问度度熊最少携带多少晶石