皮卡丘的梦想2(线段树+位运算)
来源:互联网 发布:人工智能替代人类 编辑:程序博客网 时间:2024/04/26 04:18
皮卡丘的梦想2
Time Limit: 1000MS Memory Limit: 65536KB
Submit Statistic
Problem Description
一天,一只住在 501 实验室的皮卡丘决定发奋学习,成为像 LeiQ 一样的巨巨,于是他向镇上的贤者金桔请教如何才能进化成一只雷丘。
金桔告诉他需要进化石才能进化,并给了他一个地图,地图上有 n 个小镇,他需要从这些小镇中收集进化石。
接下来他会进行 q 次操作,可能是打听进化石的信息,也可能是向你询问第 l 个小镇到第 r 个小镇之间的进化石种类。
如果是打听信息,则皮卡丘会得到一个小镇的进化石变化信息,可能是引入了新的进化石,也可能是失去了全部的某种进化石。
如果是向你询问,你需要回答他第 l 个小镇到第 r 个小镇之间的进化石种类。
Input
首先输入一个整数 T (1 <= T <= 10),代表有 T 组数据。
每组数据的第一行输入一个整数 n (1 <= n <= 100000) 和一个整数 q (1 <= q <= 100000),分别代表有 n 个小镇,表皮卡丘有 q 次操作。
接下来输入 q 行,对于每次操作,先输入操作类型,然后根据操作类型读入:
1: 紧接着输入 2 个整数 a (1 <= a <= n), b (1 <= b <= 60),表示第 a 个小镇引入了第 b 种进化石
2: 紧接着输入 2 个整数 a (1 <= a <= n), b (1 <= b <= 60),表示第 a 个小镇失去了全部第 b 种进化石
3: 紧接着输入 2 个整数 l, r (1 <= l <= r <= n),表示他想询问从第 l 个到第 r 个小镇上可收集的进化石有哪几种
Output
对于每组输入,首先输出一行 “Case T:”,表示当前是第几组数据。
对于每组数据中的每次 3 操作,在一行中按编号升序输出所有可收集的进化石。如果没有进化石可收集,则输出一个 MeiK 的百分号 “%”(不包括引号)。
Example Input
1
10 10
3 1 10
1 1 50
3 1 5
1 2 20
3 1 1
3 1 2
2 1 50
2 2 20
3 1 2
3 1 10
Example Output
Case 1:
%
50
50
20 50
%
%
题解:很明显是用线段树来维护操作。可是用什么来存储状态呢?想了想,用二进制01来表示石头的有无。然后用位运算来支持操作。
代码:
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<algorithm>#include<vector>#include<string.h>#define ll long longusing namespace std;const int N=1e5+10;ll sum[N<<2];int t,n,q;int pos,val,op;void pushup(int rt){ sum[rt]=sum[rt<<1]|sum[rt<<1|1];}void build(int l,int r,int rt){ if(l==r) { sum[rt]=0; return ; } int mid=(r+l)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt);}void add(int l,int r,int pos,int val,int rt){ if(l==r) { sum[rt]|=1ll<<(val-1); return ; } int mid=(r+l)>>1; if(pos<=mid) add(l,mid,pos,val,rt<<1); else add(mid+1,r,pos,val,rt<<1|1); pushup(rt);}void del(int l,int r,int pos,int val,int rt){ if(l==r) { sum[rt]&=~(1ll<<(val-1)); return ; } int mid=(r+l)>>1; if(pos<=mid) del(l,mid,pos,val,rt<<1); else del(mid+1,r,pos,val,rt<<1|1); pushup(rt);}ll query(int l,int r,int L,int R,int rt){ if(L<=l&&R>=r) { return sum[rt]; } ll ans=0; int mid=(r+l)>>1; if(L<=mid) ans|=query(l,mid,L,R,rt<<1); if(R>mid) ans|=query(mid+1,r,L,R,rt<<1|1); return ans;}int main(){ scanf("%d",&t); for(int k=1;k<=t;k++) { printf("Case %d:\n",k); scanf("%d%d",&n,&q); build(1,n,1); while(q--) { scanf("%d",&op); scanf("%d%d",&pos,&val); if(op==1) { add(1,n,pos,val,1); } if(op==2) { del(1,n,pos,val,1); } if(op==3) { ll ans=query(1,n,pos,val,1); ll cnt=0; bool flag=true; int ot=1; while(ans) { if(ans&1) { if(flag) flag=false; else printf(" "); printf("%d",ot); } ot++; ans>>=1; } if(flag) { printf("%%\n"); } else printf("\n"); } } } return 0;}
- 皮卡丘的梦想2(线段树+位运算)
- 【位运算 && 线段树】SDUT 3930 皮卡丘的梦想2
- sdutoj 皮卡丘的梦想2 状态压缩+线段树
- 皮卡丘的梦想2
- SDUT 3513 皮卡丘的梦想 (二进制+线段树) -- 解题报告
- 皮卡丘的梦想
- 山东理工大学2017校赛 3930皮卡丘的梦想2—线段树加状压 3926bLue的二叉树-KMP或hash 3914校赛~校赛~-打表找规律
- 师创杯”山东理工大学第九届ACM程序设计竞赛(网络同步赛)--I皮卡丘的梦想2
- Count Color(线段树+位运算)
- FZU 2105 位运算 (线段树)
- poj2777 线段树+位运算
- poj_2777线段树+位运算
- “师创杯”山东理工大学第九届ACM程序设计竞赛 正式赛 I.皮卡丘的梦想2【树状数组】水题
- POJ 2777 Count Color (线段树+位运算)
- POJ 2777 Count Color(线段树+位运算)
- POJ 2777 Count Color(线段树+位运算)
- Count Color+POJ+线段树区间更新+位运算(lazy标志的运用)
- HDU 5023 A Corrupt Mayor's Performance Art(线段树+优美的位运算)
- 分布式锁的三种实现方式
- 开博啦~
- javascript 根据给定的id集合查询对应的值,返回 json对象
- 【图解算法】排序算法——归并排序
- Java-String与其他数据类型的转换
- 皮卡丘的梦想2(线段树+位运算)
- Linux网络基础——端口
- 大端与小端存储详解
- [ssh]ActionContext中push多个对象后在jsp中分别调用
- 数据库系统概论总结
- 使用Github搭建个人网站
- 编译原理之自顶向下语法分析方法
- 进程间通信 之 共享内存(Linux)
- 欧拉函数