[ZOJ 3324][BNUOJ 16842] Machine [线段树]
来源:互联网 发布:linux渗透测试工具 编辑:程序博客网 时间:2024/05/29 18:59
有一个神奇的机器,它由一排按键构成,在这种机器上有两种操作,第一种是同时按下[l,r]的所有键,第二种是释放[l,r]的所有键。所有的释放操作均对应一个同区间的按下操作,并且释放操作在按下操作后边进行。若一个按键被按下两次释放一次,则其还是被按下的。现在给定若干次操作,问每次操作后没有被按下的键的段数。如果一段区间[l,r]里的所有的键都没有被按下,那么他们算作一段。
数据范围:总长度不超过10^8,操作次数不超过20000
先对数据离散化,因为只有2W次操作,操作又是成对出现的,所以最多出现2W个不同的点,假使每两个点之间都还有其他的点,这些点永远是相同状态的所以可以缩成一个点。这样最多有4W个叶子节点。
线段树,用类似矩形面积并里边的线段树的那种算法,每个节点记录自己被按下了多少次,然后记录自己的状态,包含左边是否被按下,右边是否被按下,中间有多少个被按下的段。如果该段是整体被按下,则中间被按下的段记录为-1。没有懒操作。仅在某个节点的所有祖先节点都没有被按下的情况下,这个节点的信息才是有效的,否则这个结点一定是全被按下的。
#include <cstdio>#include <cstring>#include <map>#include <set>using namespace std;struct State{bool l,r;int n;State() {n=-1;l=r=true;}State(bool ll,bool rr,int nn) {l=ll;r=rr;n=nn;}};struct Opt {int l,r;bool p;void read() {char c;scanf(" %c",&c);p=(c=='p');scanf("%d%d",&l,&r);}};struct Node {int l,r,times;State s;Node *ls,*rs;Node() {}Node(int ll,int rr) {l=ll;r=rr;ls=rs=NULL;s=State();times=0;}void update() {if (times!=0) {s=State(false,false,0);return;}s=State(true,true,-1);if (l==r) return;State sl=ls->s,sr=rs->s;s.l=sl.l;s.r=sr.r;s.n=sl.n+sr.n+sl.r+sr.l-(sl.r&&sr.l);}void *operator new(size_t,void *p) {return p;}};struct SegTree {Node *root,*cur;Node a[100000];Node *maketree(int l,int r) {Node *ans=new(cur++)Node(l,r);if (l==r) return ans;int t=(l+r)/2;ans->ls=maketree(l,t);ans->rs=maketree(t+1,r);return ans;}void clear(int n) {cur=a;root=maketree(0,n-1);}void print() {for (Node *i=a;i!=cur;i++) {//printf("Node %d: l=%d, r=%d, ls=%d, rs=%d\n",i-a,i->l,i->r,i->ls-a,i->rs-a);//printf(" press=%d state=%d,%d,%d\n",i->times,i->s.l,i->s.r,i->s.n);}}void press(Node *from,int l,int r) {if (from->l==l&&from->r==r) {from->times++;from->update();return;}int t=(from->l+from->r)/2;if (t<l) press(from->rs,l,r);else if (t>=r) press(from->ls,l,r);else {press(from->ls,l,t);press(from->rs,t+1,r);}from->update();}void release(Node *from,int l,int r) {if (from->l==l&&from->r==r) {from->times--;from->update();return;}int t=(from->l+from->r)/2;if (t<l) release(from->rs,l,r);else if (t>=r) release(from->ls,l,r);else {release(from->ls,l,t);release(from->rs,t+1,r);}from->update();}};set <int> c;map <int,int> d;int n,m,p;Opt b[20000];SegTree a;int main() {int t,tt,last,i;scanf("%d",&t);for (tt=1;tt<=t;tt++) {printf("Case #%d:\n",tt);scanf("%d%d",&n,&m);c.clear();d.clear();for (i=0;i<m;i++) {b[i].read();c.insert(b[i].l);c.insert(b[i].r);}p=0;last=-1;for (set<int>::iterator it=c.begin();it!=c.end();it++) {if (*it-1!=last) p++;//printf("tran: %d %d\n",*it,p);d[last=*it]=p++;}if (last!=n-1) p++;a.clear(p);for (i=0;i<m;i++) {if (b[i].p) a.press(a.root,d[b[i].l],d[b[i].r]);else a.release(a.root,d[b[i].l],d[b[i].r]);State tmp=a.root->s;printf("%d\n",tmp.n+tmp.l+tmp.r);//a.print();}}return 0;}
0 0
- [ZOJ 3324][BNUOJ 16842] Machine [线段树]
- ZOJ 3324 Machine(线段树)
- ZOJ 3324 Machine(线段树区间合并)
- ZOJ 3324 Machine 线段数 区间合并
- ZOJ - 3324 Machine
- ZOJ 3324 Machine
- ZOJ 3324Machine
- Machine+zoj+二叉树
- bnuoj 49100超级线段树并查集
- Machine - ZOJ 3805 二叉树
- zoj zju 3324 线段树 离散化
- zoj 3324 线段树+离散化
- zoj 1610 线段树
- zoj 1610 线段树
- zoj 3635 线段树
- zoj 3724 线段树
- ZOJ 3686 线段树
- ZOJ 3635 线段树
- altium designer打印 1:1 (打印机属性务必选择按照实际尺寸打印)
- Lua笔记之string详解
- 在Photoshop中用javascript复制图像并添加编号
- vc 防止界面卡死的方法
- ASP.NET中IsPostBack详解
- [ZOJ 3324][BNUOJ 16842] Machine [线段树]
- java多线程总结笔记2——线程池
- spinner的应用
- pdf转换成ppt转换器破解版
- 字典树简单应用
- 风水大师陶建国:风水也是科学
- linux -- 文件夹配置详解
- Android L Preview Root教程
- webkit内核源代码导读