U41571 Agent2

题目背景

炎炎夏日还没有过去,Agent们没有一个想出去外面搞事情的。每当ENLIGHTENED总部组织活动时,人人都说有空,结果到了活动日,却一个接着一个咕咕咕了。只有不咕鸟Lyn_king一个人冒着太阳等了半个多小时,然后居然看到连ENLIGHTENED行动参谋咕咕咕了,果然咕咕咕是人类的本性啊。

题目描述

作为一个ENLIGHTENED行动指挥,自然不想看到这一点,于是他偷取到了那些经常咕咕咕Agent的在下来N天的活动安排表,并且叫上了你来整理。在整理过程中,ENLIGHTENED行动指挥对你说了M条命令,命令操作如下。

  1. 输入0​ a​ b​,这代表在第a​天到第b​天,有一名Agent要咕咕咕。
  2. 输入1 a,这代表ENLIGHTENED行动指挥询问你根据目前的信息,在第a天有多少名Agent会咕咕咕。

作为同是不咕鸟的你,也想要惩戒那些经常咕咕咕的人,所以,请协助完成ENLIGHTENED行动指挥完成整理,并且在他每次询问时,输出正确的答案。

输入输出格式

输入格式:

第一行输入两个整数输N,M, 下来M行,每行输入一个命令,命令格式见题目描述。

输出格式:

对于每一次询问的操作,都要输出询问的答案。答案之间用换行隔开。

输入输出样例

输入样例#1: 复制

5 5
0 1 2
0 1 5
1 1
0 3 5
1 5

输出样例#1: 复制

2
2

说明

对于20%的数据N,M≤10

对于40%的数据N,M≤103

对于60%的数据N,M≤105

对于100%的数据1≤a,b≤N≤107,M≤4∗105

这道题签到题,难点在数据范围,普通线段树肯定做不了,所以采用动态开节点,要查询的才建立节点即可。

然而一开始疯狂乱错,原因是中间某个地方写了+=后面又加了一遍...

也可以用树状数组做,代码非常简洁。

#include<bits/stdc++.h>
using namespace std;int n, m;struct Node {Node *ls, *rs;int sum, tag;
} pool[32*400005], *tail = pool, *zero, *root;Node *newnode() {Node *nd = ++ tail;nd -> ls = zero;nd -> rs = zero;nd -> sum = 0;nd -> tag = 0;return nd;
}void push_down(Node *nd, int l, int r) {if(nd -> tag) {int mid = (l + r) >> 1;if(nd -> ls == zero)    nd -> ls = newnode();nd -> ls -> sum = nd -> ls -> sum + nd -> tag * (mid - l + 1);if(nd -> rs == zero)    nd -> rs = newnode();nd -> rs -> sum = nd -> rs -> sum + nd -> tag * (r - mid);nd -> ls -> tag += nd -> tag;nd -> rs -> tag += nd -> tag;nd -> tag = 0;}
}void add(Node *nd, int l, int r, int L, int R, int d) {if(l >= L && r <= R) {nd -> sum = nd -> sum + (r - l + 1) * d;nd -> tag += d;return ;}push_down(nd, l, r);int mid = (l + r) >> 1;if(L <= mid) {if(nd -> ls == zero)    nd -> ls = newnode();add(nd -> ls, l, mid, L, R, d);}if(R > mid)    {if(nd -> rs == zero)    nd -> rs = newnode();add(nd -> rs, mid + 1, r, L, R, d);}
}int query(Node *nd, int l, int r, int pos) {if(l == r)    return nd -> sum;push_down(nd, l, r);int mid = (l + r) >> 1;if(pos <= mid) return query(nd -> ls, l, mid, pos);else return query(nd -> rs, mid + 1, r, pos);
}int main() {zero = ++ tail; zero -> ls = zero;zero -> rs = zero;zero -> sum = 0;zero -> tag = 0;scanf("%d%d", &n, &m);root = newnode();for(int i = 1; i <= m; i ++) {int opt, l, r;scanf("%d", &opt);if(opt == 0) {scanf("%d%d", &l, &r);add(root, 1, n, l, r, 1);} else {scanf("%d", &l);printf("%d\n", query(root, 1, n, l));}}return 0;
}


树状数组:

#include<bits/stdc++.h>
using namespace std;int n, m;int lowbit(int x) {return x & -x;
}int pre[10000005];
void add(int pos, int d) {for(int i = pos; i <= n; i += lowbit(i))pre[i] += d;
}int query(int pos) {int ans = 0;for(int i = pos; i; i -= lowbit(i))ans += pre[i];return ans;
}int main() {scanf("%d%d", &n, &m);for(int i = 1; i <= m; i ++) {int opt, l, r;scanf("%d", &opt);if(opt == 0) {scanf("%d%d", &l, &r);add(l, 1);add(r+1, -1);} else {scanf("%d", &l);printf("%d\n", query(l));}}return 0;
}

U41572 Portal2

题目背景

某地ENLIGHTENEDXM研究所正在研究Portal的处理法则,想要揭示XM能量的来源以及应用XM能量ENLIGHTENED的首席科学家Jacks发现其能量的运算法则以及运算方法,但是方法十分复杂,仅靠人手工计算是很难算出答案的,所以它需要你协助他完成计算。

题目描述

Portal计算XM能量是通过个2个栈(0号栈,1号栈)实现的,它把对XM能量的操作如下

PUSH X NUM

把NUMNUM加入到X号栈的栈顶。

POP X

把XX号栈的栈顶元素删除。

ADD X

取出0号栈和1号栈的元素各一个,并且把它的和放入X号栈。

SUB X

取出0号栈和1号栈的元素各一个,并且把它的差的绝对值放入X号栈。

DEL X

清空X号栈中所有元素不管栈是否为空。

MOVE X Y

循环操直到Y号栈为空,把Y号栈的栈顶元素加入到X号栈,删除Y号栈的栈顶元素。

数据保证X和Y不相同

SWAP

将两个栈的所有元素调换。

END

代表命令结束,并且分两行分别输出0号栈和1号栈由栈顶到栈底的元素的值,若栈内无元素,输出NONE。数据保证指令以END结束且仅有一个END,并且也需要输出SUCCESS

AKNOI

等为无效操作,无效操作后不接数字。

更正不会有类似无效操作

对于每一行指令,若当前指令成功执行输出SUCCESS,若取出或删除元素时栈内为空或者没有对应指令输出UNSUCCESS并且不执行该行指令。

输入输出格式

输入格式:

输入若干行指令,以END指令结束

输出格式:

对于每一次操作,都要对应输出SUCCESS或者UNSUCCESS,对于END根据指令描述输出栈内元素。

输入输出样例

输入样例#1: 复制

PUSH 0 10
PUSH 0 20
PUSH 0 30
PUSH 0 40
PUSH 1 50
PUSH 1 60
ADD 0
ADD 0
ADD 0
END

输出样例#1: 复制

SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
UNSUCCESS
SUCCESS
150 30 20 10
NONE

输入样例#2: 复制

PUSH 0 10
PUSH 0 20
PUSH 0 30
PUSH 0 40
PUSH 1 50
PUSH 1 60
MOVE 0 1
END

输出样例#2: 复制

SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
SUCCESS
50 60 40 30 20 10
NONE

说明

对于20%的数据 数据保证不会出现MOVE/SWAP操作,命令总数 ≤ 100

对于40%的数据 命令总数 ≤ 1000

对于60%的数据 数据保证MOVE/SWAP的操作次数不会超过10000次,命令总数 ≤ 10^5

对于100%的数据 0 ≤ X,Y ≤ 1,命令总数≤10^6

数据保证无论任何情况,栈中元素的值X满足0≤ x ≤2^63-1​

学到了新东西!!链表模拟。

一开始总觉得链表全都是像建边的邻接链表那样,做了这道题有所感悟!

这道题要求满足两个栈的同时维护,比较困难的操作有$swap$和$move$以及$del$,暴力模拟都需要$O(n)$。所以这里就是链表模拟的套路了?

两个栈之间建立新节点2作为过渡,所有操作都用双头链表,新节点的$pre$连第一个栈,$nex$连第二个栈。

上面是链接链表的主要操作。$push$就是把要插入的值插入到哪两个点之间。

$swap$:感谢$Abyssful$的教导!如何快速交换两个数组内所有的值?记录$stk[0/1]$表示0数组和1数组当前存的是哪个数组内的东西。初始化是$stk[0]=0,stk[1]=1$,访问时$a[stk[0]][...],a[stk[1]][...]$来分别访问两个数组。这道题同理,只是因为用链表储存了两个栈,所以通过$stk[0/1]$来确定访问$pre[2]$还是$nex[2]$。

$move$:将一个栈所有元素移到另一个栈中,并且是边从栈顶取边移过去。所以首先要把两个栈顶连起来,再看是哪边移到哪边,$y->x$,就把$y$的尾和新节点相连,再把$y$那边清空即可,$x$同理。判断一下是0还是1就可以判断是移到哪里了。

$del$:直接把要清空的那边直接连到新节点就行了。

输出就沿着双头链表走到头就行了。

#include<bits/stdc++.h>
#define LL long long
using namespace std;char s[105];int nex[1000005], pre[1000005];
LL val[1000005];
int cnt = 2;void link(int u, int v) {nex[u] = v;pre[v] = u;
}void lpush(int u, int v, LL w) {val[++cnt] = w;link(u, cnt);link(cnt, v);
}void push(int x, LL w) {if(x == 0)    lpush(pre[2], 2, w);else lpush(2, nex[2], w);
}LL pop(int u) {link(pre[u], nex[u]);return val[u];
}void print(int u) {if(u) {if(nex[2] == 1) {printf("NONE\n");return ;}for(int i = nex[2]; i != 1; i = nex[i])printf("%lld ", val[i]);printf("\n");} else {if(!pre[2]) {printf("NONE\n");return ;}for(int i = pre[2]; i != 0; i = pre[i])printf("%lld ", val[i]);printf("\n");}
}int stk[2];
void print() {if(stk[0]) {print(1); print(0);} else {print(0); print(1);}
}bool sov(char *s) {int x, y;LL num;if(s[0] == 'P') {if(s[1] == 'U') {scanf("%d%lld", &x, &num);x = stk[x];push(x, num);} else {scanf("%d", &x);x = stk[x];if(x == 0) {if(pre[2] == 0)    return 0;pop(pre[2]);}else {if(nex[2] == 1)    return 0;pop(nex[2]);}}} else if(s[0] == 'A') {scanf("%d", &x);x = stk[x];if(pre[2] == 0 || nex[2] == 1)    return 0;push(x, pop(pre[2]) + pop(nex[2]));} else if(s[0] == 'S') {if(s[1] == 'U') {scanf("%d", &x);x = stk[x];if(pre[2] == 0 || nex[2] == 1)    return 0;push(x, abs(pop(pre[2]) - pop(nex[2])));} else {swap(stk[0], stk[1]);}} else if(s[0] == 'D') {scanf("%d", &x);x = stk[x];if(x == 0)    link(0, 2);else link(2, 1);} else if(s[0] == 'M') {scanf("%d%d", &x, &y);x = stk[x], y = stk[y];link(pre[2], nex[2]);if(x == 0) {link(pre[1], 2);link(2, 1);} else {link(2, nex[0]);link(0, 2);}}return 1;
}int main() {stk[0] = 0, stk[1] = 1;link(0, 2); link(2, 1);while(~scanf("%s", s)) {if(s[0] == 'E') {puts("SUCCESS");print();break;}if(sov(s))    puts("SUCCESS");else puts("UNSUCCESS");}return 0;
}

U41573 War2

题目背景

XM大战如期而至,Agent们齐聚一地,展开最后的对决。对战有很多种方式,有些复杂的方式可以获得更高的分数。可惜ENLIGHTENED的人并不怎么聪明,只会简单的hack,所以ENLIGHTENED行动指挥找到了你来做他们的总参谋。

题目描述

地图上有N个Portal,现在某一名Agent的任务是占领该地图上的M个Portal,这名Agent占领第i个Portal可以得到的分数为A[i],除了直接占领,还有其他的K种加分方式,对于着N个Portal,在占领完第X[i]个Portal后占领第Y[i]个Portal可以获得B[i]的加分,加分可能会有重复。Agent希望他可以为团队争取更多的分数,所以请求作为大战参谋的你来帮助他。

输入输出格式

输入格式:

第一行是输入三个整数N,M,K 第二行输入是N个数,第i个数代表A[i]的值。 下面K行每行有3个整数X[i],Y[i],C[i],表示在占领完第X[i]个Portal后占领第Y[i]个Portal可以获得B[i]的加分

输出格式:

输出仅一行一个整数,为该名Agent可以获得的最大分数值。

输入输出样例

输入样例#1: 复制

3 2 1
1 1 1
1 2 3

输出样例#1: 复制

5

输入样例#2: 复制

4 3 2
1 1 1 1
4 3 2
3 2 1

输出样例#2: 复制

6

说明

对于20%的数据 1≤M≤N≤4,0≤A[i],B[i]≤103

对于40%的数据 1≤M≤N≤8,0≤A[i],B[i]≤105

对于60%的数据 1≤M≤N≤12,0≤A[i],B[i]≤107

对于100%的数据 1≤M,X[i],Y[i]≤N≤18,0≤K≤N^2−N,0≤A[i],B[i]≤10^9

一道比较好想+写的状压DP,然而一开始很慌,题两次没看清楚。

分数累加的意思是如果有重复的$a$和$b$,他们的分数是可以累加起来的。

而$a$到$b$是严格要求$b$在$a$后面第一个,所以状态还要定义一个最后占领的。然后转移就行了。

#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;int n, m, k;
LL dp[(1<<18) + 1][20], qwq[20], zty[20][20];
int cnt[(1<<18) + 1];int countt(int s) {int num = 0;while(s) {num += s & 1;s >>= 1;}return num;
}LL cot(int s) {LL ans = 0;for(int i = 1; i <= n; i ++)if((s >> (i-1)) & 1)ans += qwq[i];return ans;
}void init() {for(int i = 0; i < (1 << n); i ++)cnt[i] = countt(i);
}int main() {scanf("%d%d%d", &n, &m, &k);init();for(int i = 1; i <= n; i ++)    scanf("%lld", &qwq[i]);for(int i = 1; i <= k; i ++) {int a, b;LL c;scanf("%d%d%lld", &a, &b, &c);zty[a][b] += c;}for(RG int s = 0; s < (1 << n); s ++) {if(cnt[s] >= m) continue;for(RG int i = 1; i <= n; i ++)if(!((s >> (i-1)) & 1))for(RG int j = 1; j <= n; j ++)if((s >> (j-1)) & 1)if(zty[j][i])dp[s|(1 << (i-1))][i] = max(dp[s|(1 << (i-1))][i], dp[s][j] + zty[j][i]);}LL ans = 0;for(int s = 0; s < (1 << n); s ++)for(int i = 1; i <= n; i ++)if(cnt[s] == m)ans = max(ans, dp[s][i] + cot(s));printf("%lld", ans);return 0;
}

转载于:https://www.cnblogs.com/wans-caesar-02111007/p/9751485.html

【洛谷】NOIP提高组模拟赛Day2【动态开节点/树状数组】【双头链表模拟】相关推荐

  1. [NOI Online 2022 提高组] 丹钓战(单调栈 + 树状数组 / 主席树)

    problem luogu-P8251 solution 按照题意模拟单调栈. 求出对于 iii 而言,当时单调栈的栈顶元素记为 pip_ipi​. 如果到 iii 时,栈顶已经为 pip_ipi​ ...

  2. 洛谷 P2163 [SHOI2007]园丁的烦恼 (离线sort,树状数组,解决三维偏序问题)

    P2163 [SHOI2007]园丁的烦恼 题目描述 很久很久以前,在遥远的大陆上有一个美丽的国家.统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草. 有一天国王漫步在花园 ...

  3. YbtOJ#20237-[冲刺NOIP2020模拟赛Day10]区间均值【树状数组】

    正题 题目链接:https://www.ybtoj.com.cn/contest/68/problem/1 题目大意 nnn个数字的序列,求有多少个区间[l,r][l,r][l,r]的平均值在[L,R ...

  4. 2018蓝桥杯模拟赛·青出于蓝而胜于蓝 DFS序+树状数组

    武当派一共有 nnn 人,门派内 nnn 人按照武功高低进行排名,武功最高的人排名第 111,次高的人排名第 222,... 武功最低的人排名第 nnn.现在我们用武功的排名来给每个人标号,除了祖师爷 ...

  5. 【2018ACM山东省赛 - E】Sequence(树状数组,思维,优化)

    题干: We define an element aia_iai​ in a sequence "good", if and only if there exists a j(1≤ ...

  6. AcWing 蓝桥杯AB组辅导课 05、树状数组与线段树

    文章目录 前言 一.树状数组 1.1.树状数组知识点 1.2.树状数组代码模板 模板题:AcWing 1264. 动态求连续区间和 例题 例题1.AcWing 1265. 数星星[中等,信息学奥赛一本 ...

  7. 第一届『Citric杯』NOIP提高组模拟赛 题解

    [官方题解]第一届『Citric杯』NOIP提高组模拟赛 题解 第一题 柠檬超市 这题是本次模拟赛的送分题.做法显然. 但是注意此题有一个陷阱: 注意W和C的规模都是10^9,所以如果直接用doubl ...

  8. {小结}2016.6.11【初中部 NOIP提高组 】模拟赛C

    2016.6.11[初中部 NOIP提高组 ]模拟赛C No.1!!! 100+33.3+10+90=233.3 23333 1298. 牛棚(graze2.pas/c/cpp) 题解 1299. 洗 ...

  9. 2018.12.08【NOIP提高组】模拟B组总结(未完成)

    2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...

最新文章

  1. HTML5实现屏幕手势解锁(转载)
  2. CSS中清除浮动的两种方式
  3. mongodb atlas_如何使用MongoDB Atlas将MERN应用程序部署到Heroku
  4. Java数据库篇8——索引、视图、存储过程、触发器
  5. java -从小到大排序
  6. 【VB.NET】VB.NET程序设计学习指南
  7. Hystrix面试 - 基于 timeout 机制为服务接口调用超时提供安全保护
  8. 2019 牛客多校第一场 E ABBA
  9. java笔记:第6章 面向对象程序设计
  10. 阶段3 3.SpringMVC·_06.异常处理及拦截器_7 SpringMVC拦截器之拦截器接口方法演示
  11. 永磁同步电机最大转矩电流比(PMSM-MTPA)Simulink仿真教程
  12. C# 谷歌邮箱发送邮件
  13. android+刷机文件,【技术】刷机脚本文件的修改
  14. JavaSE_05【数组】拓展练习
  15. 香港部分超市因内地游客抢购奶粉发出限购令
  16. 免费顶级域名TK介绍
  17. ftp、sftp利用bat脚本自动下载以及上传文件
  18. selenium wedriver镜像地址
  19. java suspend() 和 resume(),java多線程之(suspend()、resume())
  20. 性能服务器石墨和化合物区别,南开大学陈军教授Nano Lett. :具有高容量和快速钠离子存储性能的硫化锑-石墨烯化合物...

热门文章

  1. HTML源码小游戏——坦克大战、飞机大战、捕鱼达人
  2. office2007安装找不到文件问题
  3. 重读《学习JavaScript数据结构与算法-第三版》- 第6章 链表(一)
  4. 牧牛商学院,区块链技术在会计领域的应用
  5. 百变精灵、灵萌仙宠,《神都降魔》带您遨游仙界!
  6. 一加6可以刷的rom_一加手机怎么刷MIUI系统
  7. 关于全球苹果手机的型号版本介绍
  8. SUSE12 LVM- Logical Volume Manager(逻辑卷管理)实例
  9. 三大web服务器比较
  10. 格灵深瞳——人脸识别算法测试FRVT