线段树

线段树-区间更新-HDU 1689

天大地大妈咪最大 提交于 2020-01-09 23:56:46
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; #define maxn 200005 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define ULL unsigned long long const long long INF=0x3fffffff; int n,m; LL add[maxn<<2]; LL sum[maxn<<2]; void pushUp(int root) { sum[root]=sum[root<<1]+sum[root<<1|1]; } void pushDown(int root,int m) { if(add[root]>0) { add[root<<1]=add

[线段树][Splay][树状数组]JZOJ 3292 发牌

我怕爱的太早我们不能终老 提交于 2020-01-08 16:17:00
Description 在一些扑克游戏里,如德州扑克,发牌是有讲究的。一般称呼专业的发牌手为荷官。荷官在发牌前,先要销牌(burn card)。所谓销牌,就是把当前在牌库顶的那一张牌移动到牌库底,它用来防止玩家猜牌而影响游戏。 假设一开始,荷官拿出了一副新牌,这副牌有N张不同的牌,编号依次为1到N。由于是新牌,所以牌是按照顺序排好的,从牌库顶开始,依次为1, 2,……直到N,N号牌在牌库底。为了发完所有的牌,荷官会进行N次发牌操作,在第i次发牌之前,他会连续进行Ri次销牌操作,Ri由输入给定。请问最后玩家拿到这副牌的顺序是什么样的? 举个例子,假设N = 4,则一开始的时候,牌库中牌的构成顺序为{1, 2, 3, 4}。 假设R1=2,则荷官应该连销两次牌,将1和2放入牌库底,再将3发给玩家。目前牌库中的牌顺序为{4, 1, 2}。 假设R2=0,荷官不需要销牌,直接将4发给玩家,目前牌库中的牌顺序为{1,2}。 假设R3=3,则荷官依次销去了1, 2, 1,再将2发给了玩家。目前牌库仅剩下一张牌1。 假设R4=2,荷官在重复销去两次1之后,还是将1发给了玩家,这是因为1是牌库中唯一的一张牌。 Input 第 1行,一个整数 N,表示牌的数量。 第 2行到第 N + 1行,在第 i + 1行,有一个整数Ri, 0≤Ri<N Output 第 1行到第N行:第 i行只有一个整数

P1558 色板游戏 状压线段树

﹥>﹥吖頭↗ 提交于 2020-01-08 16:16:29
P1558 色板游戏 状压线段树 题面 洛谷P1558 每次不同颜色覆盖一段区间,每次询问一段区间有多少种颜色 因为颜色数 \(T\) 很小,使用二进制表示状态当前区间有那些颜色,二进制第 \(i\) 位表示此区间是否含有 \(i\) 这种颜色,线段树合并信息时左右儿子信息或一下就好了。 scanf 读入 char 炸了我好久,最后换成 cin 就 AC 了 AC Code: #include <iostream> #define MAXN 100010 #define sl (x<<1) #define sr (x<<1|1) #define LL long long using namespace std; int l,t,o; inline void m_swap(int &a, int &b){ int t=a; a=b; b=t; } struct nod{ int l, r; LL val, lazy; } tre[MAXN*4]; void push_up(int x){ tre[x].val = tre[sl].val|tre[sr].val; } void built(int x, int l, int r){ tre[x].l=l,tre[x].r=r; if(l==r){ tre[x].val=1; return; } int mid=(l+r)>>1;

poj 2777 Count Color 线段树

泪湿孤枕 提交于 2020-01-08 16:15:58
Count Color Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 27842 Accepted: 8337 Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board: 1. "C A B C" Color the

hdoj 4325 Flowers 线段树+离散化

穿精又带淫゛_ 提交于 2020-01-08 10:18:24
hdoj 4325 Flowers 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4325 思路: 直接线段树,按照花的开放区间的大小建树,要注意虽然花的周期数据可能会达到1e9,这样的话线段树开四倍时不可能的。但是我们可以看到一共可能的数据时N行,那么每行两个数,再开4倍的区间。计算下来,在离散化的帮助下,我们只需要开8*N被的线段树即可。 另外询问的数据也需要放入离散化的范围,如果不这样做,有可能在询问时使用lower_bound函数会导致数据的改变,询问的原数据发生变化。 eg:1~3 7~10 询问6,结果应该时0,但因为lower_bound的原因询问时使用7,得到结果1。etc. 代码: #include <iostream> #include <algorithm> #include <stdio.h> #include <string.h> #include <math.h> using namespace std; const int maxn = 1e5+5; struct node { int l,r,sum,lazy; inline void update(int val) { lazy+=val; sum+=val; } } tr[maxn*8]; int a[maxn],b[maxn],c[maxn<<1

cf1284D——线段树,排序

半城伤御伤魂 提交于 2020-01-06 15:30:53
/* 原问题可以简化成:给定n对区间[sai,eai],[sbi,ebi], 是否存在i,j,使[sai,eai],[saj,eaj] 与[sbi,ebi],[sbj,ebj]有且仅有一组相交 思路:遍历第i对区间,先找到a部分和[sai,eai]相交的所有段,设这个段的集合为S, 由于题意,S中所有b部分的段都要和[sbi,ebi]相交,这就要求S中最小的ebj>=sbi,最大的sbj<=ebi 所以想到一开始就对所有的段,按照eai升序排序,然后二分找到[x,i-1]的段a部分和i的a部分相交, 再用线段树查询b部分两端的极值,和bi进行比较即可 最后swap一下ab再算一次就好 */ #include<bits/stdc++.h> #define N 200005 using namespace std; struct Seg{int sa,ea,sb,eb;}p[N]; int cmp(Seg &a,Seg &b){ if(a.ea!=b.ea)return a.ea<b.ea; else return a.sa<b.sa; } int n,mx[4*N], mi[4*N]; void creat(int l, int r, int k) { if(l == r){ mx[k]=p[l].sb, mi[k]=p[l].eb; return ; } int mid = (l

Tunnel Warfare 线段树 区间合并|最大最小值

泄露秘密 提交于 2020-01-05 04:14:58
B - Tunnel Warfare HDU - 1540 这个有两种方法,一个是区间和并,这个我个人感觉异常恶心 第二种方法就是找最大最小值 kuangbin——线段树专题 H - Tunnel Warfare <-- 这个博客讲的很清楚 #include <cstdio>//法一:最大值最小值法,这个就是每一个点,如果这个点没有被摧毁,那就找到这个点最左边的和最右边的 #include <cstdlib>//最大-最小+1.这个就是这个最大连续长度。 #include <queue>//建树,很简单,主要就是query和update。 #include <algorithm>//这个地方的怎么去找一个包含一个数的一个区间的最大最小值呢? #include <vector>//这个就是从上面往下面查询的过程中,就去找,如果是找最大值就去max,最小值就取min #include <cstring>//这个要注意建树,这个区间的最大值的意思是,小于等于这个数的最大的被炸了的村庄,这个就说明,开始最大值为0,因为没有任何一个村庄被炸 #include <string>//区间的最小值,意思是大于等于这个数,被炸了的村庄的最小值,开始为n+1.因为没有村庄被炸。 #include <iostream> #include <stack> #define inf 0x3f3f3f3f

poj 3264 Balanced Lineup(st/线段树)

筅森魡賤 提交于 2020-01-05 04:10:07
题目大意 查询一个区间输出最大值间最小值的差 用线段树写需要剪枝...本来明明是一道快乐的水题..却t了就用st写了.. 线段树 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> const int maxn=3e5+5; using namespace std; int n,m; struct node{ int maxn,minn; } tree[maxn*4]; int arr[maxn],ans1,ans2; void built(int l,int r,int now) { int mid=(l+r)/2; if(l==r) { tree[now]=(node){arr[l],arr[l]}; return ; } built(l,mid,now*2); built(mid+1,r,now*2+1); tree[now].maxn=max(tree[now*2].maxn,tree[now*2+1].maxn); tree[now].minn=min(tree[now*2].minn,tree[now*2+1].minn);

HDU 3577 Fast Arrangement (线段树区间更新)

断了今生、忘了曾经 提交于 2020-01-05 03:30:12
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3577 题意不好理解,给你数字k表示这里车最多同时坐k个人,然后有q个询问,每个询问是每个人的上车和下车时间,每个人按次序上车,问哪些人能上车输出他们的序号。 这题用线段树的成段更新,把每个人的上下车时间看做一个线段,每次上车就把这个区间都加1,但是上车的前提是这个区间上的最大值不超过k。有个坑点就是一个人上下车的时间是左闭右开区间,可以想到要是一个人下车,另一个人上车,这个情况下这个点的大小还是不变的。还有注意格式... 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 const int MAXN = 1e6 + 5; 6 struct segtree { 7 int l , r , sum , add; 8 }T[MAXN << 2]; 9 int x[MAXN / 10] , y[MAXN / 10] , ans[MAXN / 10]; 10 11 void init(int p , int l , int r) { 12 int mid = (l + r) >> 1; 13 T[p].l = l , T[p].r = r , T[p].add = 0;

线段树专题

偶尔善良 提交于 2020-01-05 03:29:29
1.hud 1166 http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 本题目涉及到了区间操作和点操作两种操作。 区间操作(区间和):我们采用了递推的方法来建树,建好了叶子结点之后,我们再回溯来建整个区间。(这个操作是关键) 点操作:点操作必然涉及到区间的改动,我们判定,只要这个点在一个区间上,那么我们就对这个区间操作。 View Code #include "iostream" #include "string" #include "algorithm" using namespace std; #define maxn 50005 int len, peo[maxn], ans; typedef struct node { int l, r, m; int s; }node; node t[maxn*4]; void build(int ll, int le, int ri) { t[ll].l = le; t[ll].r = ri; t[ll].m = (le+ri)>>1; if(le==ri) t[ll].s = peo[le]; else { build(ll<<1, le, t[ll].m); build(ll<<1|1, t[ll].m+1, ri); t[ll].s = t[ll<<1].s + t[ll<<1