题意:给定一个只含'(',')'的括号序列,有m个操作,改变某个位置的括号或者询问区间[L,R]内的括号进行配对后剩下的第K个括号的位置(配对的括号从原序列中删掉)。

思路:首先对于一个括号序列,进行配对后剩下的括号序列必定是")))...)((...(("这种形式的,令(x,y)表示当前区间的剩下的右括号数为x,左括号数为y这个状态,不难发现它可以通过子区间来合并,因此考虑用线段树解决。对于单点更新比较容易,直接在叶子节点改变一下,然后向上更新即可,对于L,R,K这个询问,首先进行一次区间[L,R]的查找,得到最终的左括号和右括号数目,如果数目和小于K,则答案为-1,否则可以确定第K个括号的是哪种类型的括号,假设第K个括号是右括号,则问题转化为求第K个右括号的位置,在线段树上二分即可,二分的时候需要注意,假定答案在右区间,且左区间有x个右括号y个左括号,则在右区间应查找第K-x+y个右括号。

 #pragma comment(linker, "/STACK:102400000,102400000")

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <deque>
#include <cmath>
#include <ctime>
#include <cctype>
#include <set>
#include <bitset>
#include <functional>
#include <numeric>
#include <stdexcept>
#include <utility>
#include <vector> using namespace std; #define mem0(a) memset(a, 0, sizeof(a))
#define mem_1(a) memset(a, -1, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define define_m int m = (l + r) >> 1
#define rep_up0(a, b) for (int a = 0; a < (b); a++)
#define rep_up1(a, b) for (int a = 1; a <= (b); a++)
#define rep_down0(a, b) for (int a = b - 1; a >= 0; a--)
#define rep_down1(a, b) for (int a = b; a > 0; a--)
#define all(a) (a).begin(), (a).end()
#define lowbit(x) ((x) & (-(x)))
#define constructInt4(name, a, b, c, d) name(int a = 0, int b = 0, int c = 0, int d = 0): a(a), b(b), c(c), d(d) {}
#define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {}
#define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {}
#define pchr(a) putchar(a)
#define pstr(a) printf("%s", a)
#define sstr(a) scanf("%s", a)
#define sint(a) scanf("%d", &a)
#define sint2(a, b) scanf("%d%d", &a, &b)
#define sint3(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define pint(a) printf("%d\n", a)
#define test_print1(a) cout << "var1 = " << a << endl
#define test_print2(a, b) cout << "var1 = " << a << ", var2 = " << b << endl
#define test_print3(a, b, c) cout << "var1 = " << a << ", var2 = " << b << ", var3 = " << c << endl typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi; const int dx[] = {, , -, , , , -, -};
const int dy[] = {-, , , , , -, , - };
const int maxn = 2e5 + ;
const int md = ;
const int inf = 1e9 + ;
const LL inf_L = 1e18 + ;
const double pi = acos(-1.0);
const double eps = 1e-; template<class T>T gcd(T a, T b){return b==?a:gcd(b,a%b);}
template<class T>bool max_update(T &a,const T &b){if(b>a){a = b; return true;}return false;}
template<class T>bool min_update(T &a,const T &b){if(b<a){a = b; return true;}return false;}
template<class T>T condition(bool f, T a, T b){return f?a:b;}
template<class T>void copy_arr(T a[], T b[], int n){rep_up0(i,n)a[i]=b[i];}
int make_id(int x, int y, int n) { return x * n + y; } int ans;
char s[maxn]; struct SegTree {
struct Node {
int cl, cr;
} tree[maxn << ]; Node merge(Node b, Node c) {
Node a;
a.cl = c.cl;
a.cr = b.cr;
if (b.cl <= c.cr) a.cr += c.cr - b.cl;
else a.cl += b.cl - c.cr;
return a;
} void build(int l, int r, int rt) {
if (l == r) {
char ch = s[l - ];
tree[rt].cl = ch == '(';
tree[rt].cr = ch == ')';
return ;
}
define_m;
build(lson);
build(rson);
tree[rt] = merge(tree[rt << ], tree[rt << | ]);
} void update(int u, int l, int r, int rt) {
if (l == r) {
swap(tree[rt].cl, tree[rt].cr);
return ;
}
define_m;
if (u <= m) update(u, lson);
else update(u, rson);
tree[rt] = merge(tree[rt << ], tree[rt << | ]);
} Node query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) return tree[rt];
define_m;
if (R <= m) return query(L, R, lson);
if (L > m) return query(L, R, rson);
return merge(query(L, R, lson), query(L, R, rson));
} Node find1(int L, int R, int k, int l, int r, int rt) {
if (L <= l && r <= R && (k > tree[rt].cr || k <= || ans)) return tree[rt];
if (l == r) {
ans = l;
return tree[rt];
}
define_m;
if (R <= m) return find1(L, R, k, lson);
if (L > m) return find1(L, R, k, rson);
Node buf = find1(L, R, k, lson);
if (ans) return buf;
return merge(buf, find1(L, R, k - buf.cr + buf.cl, rson));
} Node find2(int L, int R, int k, int l, int r, int rt) {
if (L <= l && r <= R && (k > tree[rt].cl || k <= || ans)) return tree[rt];
if (l == r) {
ans = l;
return tree[rt];
}
define_m;
if (R <= m) return find2(L, R, k, lson);
if (L > m) return find2(L, R, k, rson);
Node buf = find2(L, R, k, rson);
if (ans) return buf;
return merge(find2(L, R, k - buf.cl + buf.cr, lson), buf);
}
};
SegTree ST;
int main() {
//freopen("in.txt", "r", stdin);
int T, n, m;
cin >> T;
while (T --) {
cin >> n >> m;
scanf("%s", s);
ST.build(, n, );
rep_up0(i, m) {
int id;
sint(id);
if (id == ) {
int u;
sint(u);
ST.update(u, , n, );
}
else {
int u, v, k;
sint3(u, v, k);
SegTree::Node buf = ST.query(u, v, , n, );
if (buf.cl + buf.cr < k) {
puts("-1");
continue;
}
ans = ;
if (buf.cr >= k) ST.find1(u, v, k, , n, );
else ST.find2(u, v, buf.cl + buf.cr - k + , , n, );
printf("%d\n", ans);
}
}
}
return ;
}

[hdu5217]线段树的更多相关文章

  1. bzoj3932--可持久化线段树

    题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...

  2. codevs 1082 线段树练习 3(区间维护)

    codevs 1082 线段树练习 3  时间限制: 3 s  空间限制: 128000 KB  题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...

  3. codevs 1576 最长上升子序列的线段树优化

    题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...

  4. codevs 1080 线段树点修改

    先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...

  5. codevs 1082 线段树区间求和

    codevs 1082 线段树练习3 链接:http://codevs.cn/problem/1082/ sumv是维护求和的线段树,addv是标记这歌节点所在区间还需要加上的值. 我的线段树写法在运 ...

  6. PYOJ 44. 【HNSDFZ2016 #6】可持久化线段树

    #44. [HNSDFZ2016 #6]可持久化线段树 统计 描述 提交 自定义测试 题目描述 现有一序列 AA.您需要写一棵可持久化线段树,以实现如下操作: A v p x:对于版本v的序列,给 A ...

  7. CF719E(线段树+矩阵快速幂)

    题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作 分析:线段树 线段树的每个节点表示(f[i],f[i-1])这 ...

  8. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  9. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

随机推荐

  1. 3. pkg

    程序打包成可执行文件(.exe) 1.)  npm install -g pkg 2.)  单个文件:pkg entrance.js ( windows: pkg -t win entrance.js ...

  2. MySQL笔记总结-DML语言

    DML语言 插入 一.方式一 语法: insert into 表名(字段名,...) values(值,...); 特点: 1.要求值的类型和字段的类型要一致或兼容 2.字段的个数和顺序不一定与原始表 ...

  3. 单线程下实现IO切换

    1.Greenlet greenlet可以实现两个任务之间的来回切换,但遇到IO会阻塞,不会切(使用这个模块之前需要在电脑命令提示符中输入 pip3 install greenlet 进行安装) 例如 ...

  4. 重大更新!Druid 0.18.0 发布—Join登场,支持Java11

    Apache Druid本质就是一个分布式支持实时数据分析的数据存储系统. 能够快速的实现查询与数据分析,高可用,高扩展能力. 距离上一次更新刚过了二十多天,距离0.17版本刚过了三个多月,Druid ...

  5. 22.Java面试学习平台-整合OSS对象存储

    SpringCloud实战项目全套学习教程连载中 PassJava 学习教程 简介 PassJava-Learning项目是PassJava(佳必过)项目的学习教程.对架构.业务.技术要点进行讲解. ...

  6. 地点下来框的实现(php)

    效果图: 样式(bootstrap): class="selectpicker show-tick form-control",就是多了个form-contro就行了 概念: 这里 ...

  7. Ubuntu 设置 log 级别

    Linux环境下使用rsyslog管理日志 rsyslog linux运维 linux 22.7k 次阅读  ·  读完需要 22 分钟     在 Linux 系统中,日志文件记录了系统中包括内核. ...

  8. java中的Volatile关键字使用

    文章目录 什么时候使用volatile Happens-Before java中的Volatile关键字使用 在本文中,我们会介绍java中的一个关键字volatile. volatile的中文意思是 ...

  9. 在IBM Cloud中运行Fabric

    文章目录 打包智能合约 创建IBM Cloud services 创建fabric网络 创建org和相应的节点 创建order org和相应节点 创建和加入channel 导入智能合约 上篇文章我们讲 ...

  10. Excel导入异常Cannot get a text value from a numeric cell解决及poi导入时注意事项

    POI操作Excel时偶尔会出现Cannot get a text value from a numeric cell的异常错误. 异常原因:Excel数据Cell有不同的类型,当我们试图从一个数字类 ...