#503. 「LibreOJ β Round」ZQC 的课堂 容斥原理+Treap
题目:

题解:
比较容易发现 : \(x,y\) 的贡献是独立的。
所以可以分开考虑。
假设我们考虑 \(x\).向量在 \(x\) 方向的投影依次是 : \(\{a_1,a_2, ... ,a_n\}\)
那么在点 \(i\) 时候的 \(x\) 坐标即 : \(1 + \sum_{k=1}^ia_i\),设 \(s_i = \sum_{k=1}^ia_i\)
那么贡献即 : \(\sum_{i=1}^[(1+s_{i-1})*(1+s_i) < 0]\)
也就是 : \(\sum_{i=1}^n [max\{s_i,s_{i-1}\}>0 \space \space \&\& \space \space min\{s_i,s_{i-1}\} < 0]\)
考虑容斥原理,我们可以得到 :
\]
还有 :
\(\sum_{i=1}^n [max\{s_i,s_{i-1}\}<0 \space \space \&\& \space \space min\{s_i,s_{i-1}\} > 0]\) \(?\)
不存在的
所以用 Splay 支持单点修改,区间加上一个数和统计小于/大于零的数的个数。
分别维护即可。
后来又去写才发现自己想简单了。
按照序列序插入做和按照权值插入做都不能简单的直接应用到全局。
正确的姿势是维护一个偏移量,表示插入到Treap中的点和实际上的点偏差了多少。
所以我们可以只将操作指针右侧的点全部插入到Treap中,并且在外面记录所有在Treap中的元素与实际的相差了多少。
怎么处理每个元素实际上的偏差并不是全局的偏差?
插入的时候让这个元素向反方向偏移一下再插入,然后就可以保证所有Trie中的元素偏移量都一样了。
对于所有指针左边的点,我们知道我们修改的时候不会对左边的东西造成任何影响。
所以可以直接维护终坐标和在这段时间内跨越坐标轴的次数。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
inline void read(int &x){
x=0;static char ch;static bool flag;flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
#define mk(x,y) make_pair(x,y)
#define fst first
#define snd second
const int maxn = 100010;
struct Treap{
struct Node{
Node *ch[2];
int w,siz,fix;
void update(){
siz = ch[0]->siz + ch[1]->siz + 1;
}
}*root,mem[maxn],*it,*null;
Node *ws[maxn];int top;
inline void init(){
it = mem;null = it ++ ;
null->ch[0] = null->ch[1] = null;
null->siz = 0;null->fix = 0x3f3f3f3f;
root = null;
}
inline Node* newNode(int x){
Node *p = top ? ws[top--] : it ++ ;
p->ch[0] = p->ch[1] = null;
p->siz = 1;p->fix = rand();
p->w = x;return p;
}
inline void rotate(Node* &p,int k){
Node *x = p->ch[k^1];
p->ch[k^1] = x->ch[k];
x->ch[k] = p;
p->update();x->update();
p = x;return ;
}
void insert(Node* &p,int x){
if(p == null){
p = newNode(x);
return ;
}insert(p->ch[x >= p->w],x);
if(p->ch[x>=p->w]->fix < p->fix)
rotate(p,x<p->w);
p->update();
}
void erase(Node* &p,int x){
if(p->w == x){
if(p->ch[0] != null && p->ch[1] != null){
int k = p->ch[0]->fix < p->ch[1]->fix;
rotate(p,k);
erase(p->ch[k],x);
}else{
Node *y = p->ch[0] != null ? p->ch[0] : p->ch[1];
ws[++top] = p;p = y;
}
}else erase(p->ch[x >= p->w],x);
if(p != null) p->update();
}
inline void insert(int x){insert(root,x);}
inline void erase(int x){erase(root,x);}
inline int les(int x){
Node *p = root;
int res = 0;
while(p != null){
if(p->w > x) p = p->ch[0];
else res += p->ch[0]->siz + 1,p = p->ch[1];
}return res;
}
inline int gre(int x){
Node *p = root;
int res = 0;
while(p != null){
if(p->w < x) p = p->ch[1];
else res += p->ch[1]->siz + 1,p = p->ch[0];
}return res;
}
Treap(){init();}
}zsx[2],zsy[2];
pa a[maxn];
int X,Y,dx,dy,pot,n,ansx,ansy;
inline void move_right(){
if(pot == n) return ;++ pot;
zsx[0].erase(min(X-dx,X+a[pot].fst-dx));
zsy[0].erase(min(Y-dy,Y+a[pot].snd-dy));
zsx[1].erase(max(X-dx,X+a[pot].fst-dx));
zsy[1].erase(max(Y-dy,Y+a[pot].snd-dy));
if(X*(X+a[pot].fst) < 0) ++ ansx;
if(Y*(Y+a[pot].snd) < 0) ++ ansy;
X += a[pot].fst;Y += a[pot].snd;
}
inline void move_left(){
if(pot == 1) return ;
X -= a[pot].fst;Y -= a[pot].snd;
if(X*(X+a[pot].fst) < 0) -- ansx;
if(Y*(Y+a[pot].snd) < 0) -- ansy;
zsx[0].insert(min(X-dx,X+a[pot].fst-dx));
zsy[0].insert(min(Y-dy,Y+a[pot].snd-dy));
zsx[1].insert(max(X-dx,X+a[pot].fst-dx));
zsy[1].insert(max(Y-dy,Y+a[pot].snd-dy));
-- pot;
}
inline void modify(){
int x,y;read(x);read(y);
if(X*(X-a[pot].fst) < 0) -- ansx;
if(Y*(Y-a[pot].snd) < 0) -- ansy;
X += x - a[pot].fst;
Y += y - a[pot].snd;
dx += x - a[pot].fst;
dy += y - a[pot].snd;
a[pot] = mk(x,y);
if(X*(X-x) < 0) ++ ansx;
if(Y*(Y-y) < 0) ++ ansy;
}
inline int query(){
int res = n - pot - zsx[0].gre(-dx) - zsx[1].les(-dx) +
n - pot - zsy[0].gre(-dy) - zsy[1].les(-dy);
return res + ansx + ansy;
}
int main(){
srand(2619520);
int q;read(n);
X = Y = 1;
rep(i,1,n){
read(a[i].fst);read(a[i].snd);
zsx[0].insert(min(X,X+a[i].fst));
zsy[0].insert(min(Y,Y+a[i].snd));
zsx[1].insert(max(X,X+a[i].fst));
zsy[1].insert(max(Y,Y+a[i].snd));
X += a[i].fst;Y += a[i].snd;
}X = Y = 1;
move_right();read(q);
char ch;
while(q--){
while(ch=getchar(),ch<'!');
if(ch == 'B') move_left();
else if(ch == 'F') move_right();
else if(ch == 'C') modify();
else printf("%d\n",query());
}
return 0;
}
#503. 「LibreOJ β Round」ZQC 的课堂 容斥原理+Treap的更多相关文章
- LOJ#503. 「LibreOJ β Round」ZQC 的课堂(容斥+FHQTreap)
题面 传送门 题解 首先\(x\)和\(y\)两维互相独立,可以分开考虑,我们以\(x\)为例 我们把\(x\)做个前缀和,那么就是问有多少\(i\)满足\(s_is_{i-1}<0\),其中\ ...
- LOJ#505. 「LibreOJ β Round」ZQC 的游戏(最大流)
题意 题目链接 Sol 首先把第一个人能吃掉的食物删掉 然后对每个人预处理出能吃到的食物,直接限流跑最大流就行了 判断一下最后的最大流是否等于重量和 注意一个非常恶心的地方是需要把除1外所有人都吃不到 ...
- #505. 「LibreOJ β Round」ZQC 的游戏
题目描述 首先一定是让ZQC吃掉他能吃到的所有的球,这样才能尽可能的满足ZQC的质量是所有玩家中最大的. 在满足某一个玩家的质量不会超过ZQC的情况下,让这个玩家吃掉尽可能多的球,让其他玩家吃掉的尽可 ...
- LOJ504「LibreOJ β Round」ZQC 的手办
https://loj.ac/problem/504 题解 对于区间取\(\max\),这个比较好办,直接在线段树上打标记就行了. 如果让我们弹出前\(n\)个数,我们可以用类似超级钢琴的思想,队列中 ...
- loj#501 「LibreOJ β Round」ZQC 的树列
分析 代码(我的代码是瞎jb水过去的) #include<bits/stdc++.h> using namespace std; #define li long long li a[]; ...
- loj#500 「LibreOJ β Round」ZQC 的拼图
分析 二分倍数 然后考虑dp[i][j]表示选到第i个x轴覆盖到j的情况y轴最多覆盖多少 贡献柿子可以画图然后相似三角形得到 代码 #include<bits/stdc++.h> usin ...
- 「LibreOJ β Round」ZQC 的手办
https://loj.ac/problem/504 一类套路题. 首先这个玩意可以两个logn树套树做.... naive地,把区间内的所有数拿出来放进堆里.不断取出. 太多了. 所以开始只保留那初 ...
- [LOJ#500]「LibreOJ β Round」ZQC的拼图
题目 点这里看题目. 分析 首先不难发现答案具有单调性,因此可以二分答案.答案上限为\(V=2m\times \max\{a_i, b_i\}\). 考虑如何去判断当前的答案.设这个答案为 ...
- loj #547. 「LibreOJ β Round #7」匹配字符串
#547. 「LibreOJ β Round #7」匹配字符串 题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...
随机推荐
- app自动化测试-appium
一.环境准备(windows) 1.安装Microsoft .NET Framework 4.5 双击运行如下文件:net4.5.1.exe 2.安装node-v6.11.4-x64.msi 双击运行 ...
- jQuery UI 自定义样式的日历控件
在线演示 本地下载
- React Native 网络请求封装:使用Promise封装fetch请求
最近公司使用React作为前端框架,使用了异步请求访问,这里做下总结: React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRe ...
- java分页的实现(后台工具类和前台jsp页面)
1.首先,新建一个类Page.java public class Page implements Serializable { private static final long serialVers ...
- C++ Primer 第二章 学习笔记
在auto一个引用时,auto会忽略顶层const,而保存底层const decltype(sum()) x = i; // I的类型就是sum()返回值的类型
- 用Java编程计算出所有的"水仙花数"
题目:打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,其各位数字立方和等于该数本身.例如:153是一个 "水仙花数 ",因 ...
- ECS vs. Kubernetes 类似而又不同
C2Container Service (ECS)和Kubernetes (K8s) 都解决了同样的问题:跨越主机集群管理容器.ECS和Kubernetes之间的斗争让我想起了vi和Emacs之间的编 ...
- 智课雅思词汇---二十三、动词性后缀-ate-fy-ish-ize
智课雅思词汇---二十三.动词性后缀-ate-fy-ish-ize 一.总结 一句话总结: 1.-ate(differentiate,maturate)? 后缀:-ate ①[动词后缀] 表示做.造成 ...
- MySQL二进制日志功能介绍
二进制日志记录所有更新数据的SQL语句,其中也包含可能更新数据的SQL语句,例如DELETE语句执行过程中无匹配的行.二进制日志中还包含了与执行SQL语句相关的内容,例如SQL语句执行的时间.错误代码 ...
- 转:大数据时代快速SQL引擎-Impala
本文来自:http://blog.csdn.net/yu616568/article/details/52431835 如有侵权 可立即删除 背景 随着大数据时代的到来,Hadoop在过去几年以接近统 ...