传送门

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

Finally, you come to the interview room. You know that a Microsoft interviewer is in the room though the door is locked. There is a combination lock on the door. There are N rotators on the lock, each consists of 26 alphabetic characters, namely, 'A'-'Z'. You need to unlock the door to meet the interviewer inside. There is a note besides the lock, which shows the steps to unlock it.

Note: There are M steps totally; each step is one of the four kinds of operations shown below:

Type1: CMD 1 i j X: (i and j are integers, 1 <= i <= j <= N; X is a character, within 'A'-'Z')

This is a sequence operation: turn the ith to the jth rotators to character X (the left most rotator is defined as the 1st rotator)

For example: ABCDEFG => CMD 1 2 3 Z => AZZDEFG

Type2: CMD 2 i j K: (i, j, and K are all integers, 1 <= i <= j <= N)

This is a sequence operation: turn the ith to the jth rotators up K times ( if character A is turned up once, it is B; if Z is turned up once, it is A now. )

For example: ABCDEFG => CMD 2 2 3 1 => ACDDEFG

Type3: CMD 3 K: (K is an integer, 1 <= K <= N)

This is a concatenation operation: move the K leftmost rotators to the rightmost end.

For example: ABCDEFG => CMD 3 3 => DEFGABC

Type4: CMD 4 i j(i, j are integers, 1 <= i <= j <= N):

This is a recursive operation, which means:

If i > j:
Do Nothing
Else:
CMD 4 i+1 j
CMD 2 i j 1

For example: ABCDEFG => CMD 4 2 3 => ACEDEFG

输入

1st line:  2 integers, N, M ( 1 <= N <= 50000, 1 <= M <= 50000 )

2nd line: a string of N characters, standing for the original status of the lock.

3rd ~ (3+M-1)th lines: each line contains a string, representing one step.

输出

One line of N characters, showing the final status of the lock.

提示

Come on! You need to do these operations as fast as possible.

样例输入
7 4
ABCDEFG
CMD 1 2 5 C
CMD 2 3 7 4
CMD 3 3
CMD 4 1 7
样例输出
HIMOFIN

Analysis:

CMD 1CMD 2是裸的线段树。CMD 4看起来很“吓人”,仔细分析一下不难发现CMD 4 i j是将密码锁的i位旋转(turn up)1次,第i+1位旋转2次,第i+1位旋转3次,...这也可以用线段树维护。 为了表述方便,我们用delta[i]表示位置i上由CMD 4造成的turn up次数。做法是将线段树的每个节点(每个节点都代表一个区间(L, R))增添两个attribute:一个是delta,用来记录delta[L];另一个是inc,用来记录该区间内delta[i+1]-delta[i]的值。应当注意到当对线段树上的某个区间(节点)进行第1次CMD 4操作后,其delta值是1,inc值是1;接着进行第2次操作后,其delta值是2,inc值是2。下面考虑CMD 3CMD 3 k 实际上是将字符串(即尚在构造中的密码)循环左移k位,比如对"ABCDEFG"进行CMD 3 3操作后,它变成"DEFGABC"。这种操作似乎是和线段树的精神相违背的,其实不然。线段树维护始终都是未经过移位操作的串,若原串已经循环累计左移s位了,我们只要将对应于当前(新)串的操作区间循环右移s位(注意:右移后[L, R]可能分裂为两段),之后再放到线段树里更新。

Implementation:

先贴代码,以后再填坑。
#include <bits/stdc++.h>
using namespace std; const int N(5e4+);
int same[N<<], rot[N<<], delta[N<<], inc[N<<];
char s[N]; void build(int id, int L, int R){
if(L==R){same[id]=s[L]-'A'; return;}
int mid=(L+R)>>;
same[id]=-;
build(id<<, L, mid);
build(id<<|, mid+, R);
} void CLEAR(int id, int v){
same[id]=v, rot[id]=delta[id]=inc[id]=;
} void push_rot(int s, int f){
rot[s]+=rot[f], rot[s]%=;
} void push_inc(int s, int f, int d){
delta[s]+=d, inc[s]+=inc[f], delta[s]%=, inc[s]%=;
} void push_down(int id, int L, int R){
int ls=id<<, rs=ls|;
if(~same[id]) CLEAR(ls, same[id]), CLEAR(rs, same[id]), same[id]=-;
if(rot[id]) push_rot(ls, id), push_rot(rs, id), rot[id]=;
int mid=(R+L)>>, t=delta[id]+(mid+-L)*inc[id];
push_inc(ls, id, delta[id]), push_inc(rs, id, t%), delta[id]=inc[id]=;
} int query(int id, int L, int R, int p){
if(~same[id]) return (same[id]+rot[id]+delta[id]+(p-L)*inc[id])%;
push_down(id, L, R); //error-prone
int mid=(L+R)>>;
if(p<=mid) return query(id<<, L, mid, p);
return query(id<<|, mid+, R, p);
} void SET(int id, int L, int R, int l, int r, int v){
if(l<=L && R<=r){
CLEAR(id, v);
return;
}
push_down(id, L, R);
int mid=(L+R)>>;
if(l<=mid) SET(id<<, L, mid, l, r, v);
if(r>mid) SET(id<<|, mid+, R, l, r, v);
} void ROTATE(int id, int L, int R, int l, int r, int v){
if(l<=L && R<=r){rot[id]+=v, rot[id]%=; return;}
push_down(id, L, R);
int mid=(L+R)>>;
if(l<=mid) ROTATE(id<<, L, mid, l, r, v);
if(r>mid) ROTATE(id<<|, mid+, R, l, r, v);
} void INC_SHIFT(int id, int L, int R, int l, int r, int v){
if(l<=L && R<=r){
delta[id]+=v+L-l; //error-prone
inc[id]+=;
delta[id]%=, inc[id]%=;
return;
}
push_down(id, L, R);
int mid=(L+R)>>;
if(l<=mid) INC_SHIFT(id<<, L, mid, l, r, v); //error-prone
if(r>mid) INC_SHIFT(id<<|, mid+, R, l, r, v);
} int main(){
int n, m;
cin>>n>>m>>s;
build(, , n-);
char ch;
int shift=; //number of left shift
for(int t, l, r, k; m--; ){
scanf("%*s%d", &t);
if(t!=) cin>>l>>r, l--, r--, l=(l+shift)%n, r=(r+shift)%n;
if(t==){
cin>>ch, k=ch-'A'; //cin ignores leading spaces.
if(l<=r) SET(, , n-, l, r, k);
else SET(, , n-, l, n-, k), SET(, , n-, , r, k);
}
else if(t==){
cin>>k;
if(l<=r) ROTATE(, , n-, l, r, k);
else ROTATE(, , n-, l, n-, k), ROTATE(, , n-, , r, k);
}
else if(t==){
cin>>k, shift+=k, shift%=n;
}
else{
if(l<=r) INC_SHIFT(, , n-, l, r, );
else INC_SHIFT(, , n-, l, n-, ), INC_SHIFT(, , n-, , r, n-l+);
}
}
for(int i=; i<n; i++) putchar(query(, , n-, (i+shift)%n)+'A');
puts("");
return ;
}

实现细节:

这道题代码量相对大一些,而且有些地方容易想不清楚。

先总结一下线段树:

线段树是用来维护区间上的修改(亦称 更新/modify/update)与查询(query)的。修改与查询都可分成两类:点修改,区间修改;点查询,区间查询。

其中区间修改往往要用到 lazy-tag 技巧。线段树节点维护的所有atrribute都是关于这个节点所对应的区间的,广义而言,都可看作区间的函数

\[f([L, R])\] 这些 attribute 记录的信息可分为两类,一类是该区间的某种属性(properties),另一类是对此区间(已经)进行的某些操作(operations),或者说该区间经历 (expierenced)的某些操作。

再说说这道题的实现:

线段树的每个节点所需的 atrribute,除了 Analysis 中提到的 delta, inc(用来记录该区间经历的CMD 4操作)之外,还有

  • same,用来记录该区间经历的CMD 1操作,我们用0~25代表'A'~'Z';
  • rot,用来记录该区间所经历的CMD 2操作;

CMD 1操作会将该区间已经历的所有其他操作全部覆盖(清空)。

 
 
 
 
 
 
 

hihocoder #1058 Combination Lock的更多相关文章

  1. Combination Lock

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Finally, you come to the interview room. You know that a Micr ...

  2. 贪心 Codeforces Round #301 (Div. 2) A. Combination Lock

    题目传送门 /* 贪心水题:累加到目标数字的距离,两头找取最小值 */ #include <cstdio> #include <iostream> #include <a ...

  3. Codeforces Round #301 (Div. 2) A. Combination Lock 暴力

    A. Combination Lock Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/540/p ...

  4. Hiho----微软笔试题《Combination Lock》

    Combination Lock 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Finally, you come to the interview room. You ...

  5. CF #301 A :Combination Lock(简单循环)

    A :Combination Lock 题意就是有一个密码箱,密码是n位数,现在有一个当前箱子上显示密码A和正确密码B,求有A到B一共至少需要滚动几次: 简单循环:

  6. hihocoder-第六十一周 Combination Lock

    题目1 : Combination Lock 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Finally, you come to the interview roo ...

  7. A - Combination Lock

    Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Description Scroog ...

  8. HDU 3104 Combination Lock(数学题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3104 Problem Description A combination lock consists ...

  9. 洛谷 P2693 [USACO1.3]号码锁 Combination Lock

    P2693 [USACO1.3]号码锁 Combination Lock 题目描述 农夫约翰的奶牛不停地从他的农场中逃出来,导致了很多损害.为了防止它们再逃出来,他买了一只很大的号码锁以防止奶牛们打开 ...

随机推荐

  1. CSS3中的字体rem

    rem和em都是相对单位,em相对父元素的font-size来计算,而rem是根据文档根元素(html)的font-size大小来计算的 通常将html的字体大小设为62.5%(等于10px),当然也 ...

  2. Android Studio Jar、so、library项目依赖

    Eclipse跟AS的不同 从Eclipse到AS不要带着在Eclipse中的主观色彩去在AS中使用,从项目的构成到构建是不同的,下面列举在Eclipse和AS中的一些概念的区别: WorkSpace ...

  3. 【转】【SEE】基于SSE指令集的程序设计简介

    SSE技术简介 Intel公司的单指令多数据流式扩展(SSE,Streaming SIMD Extensions)技术能够有效增强CPU浮点运算的能力.Visual Studio .NET 2003提 ...

  4. js实现网页防止被iframe框架嵌套及几种location.href的区别

    首先我们了解一下几种location.href的区别简单的说:几种location.href的区别js实现网页被iframe框架功能,感兴趣的朋友可以了解下 首先我们了解一下:window.locat ...

  5. IT客学院《构建高转化率的着陆页-PS+HTML+网络营销》共25节【价值199元】无水印版

    课程简介本课程是全网独家专业的着陆页课程,课程完整的再现了整个着陆页实战案例的开发过程,包括:策划.设计和实现.上线后的推广.优化及提高转化率的技巧等,本套课程能帮助您迅速掌握着陆页的能力,迅速洞察完 ...

  6. Androd Studio layout页面布局无法预览

    Could not initialize class android.support.v7.internal.widget.ActionBarOverlayLayout 导致无法看到布局页面,解决方法 ...

  7. win7桌面移到其他盘

    打开"计算机",点"用户"--"Administrator"点进去,或者,打开我的文档,然后右键点"桌面""属 ...

  8. initWithNibName&initWithCoder &awakeFromNib&UIView常见属性方法

    第一.initWithNibName这个方法是在controller的类在IB中创建,但是通过Xcode实例化controller的时候用的. 第 二.initWithCoder 是一个类在IB中创建 ...

  9. Kindeditor(JSP)& 上传目录不存在

    一.基本配置 Kindeditor是一款富文本编辑器,作用跟博客园写文章用的这个编辑器一样,都是为了让文本加入各种各样的修饰元素. 使用方法如下,解压缩,把期中的ASP\NET\PHP文件夹都删除,然 ...

  10. 使用git提交本地代码到github

    1. 客户端选择 git在本地,有多种客户端可供选择,比如eclipse的插件EGit,还有git的官方客户端: Git  Bash, Git CMD, Git GUI等. 推荐使用官方的Git Ba ...