LOJ


看到离线区间操作仍然考虑莫队,然后可以发现:我们对于原来的凸包集合按照极角序维护一个链表,那么删除一个位置可以\(O(1)\),撤回删除操作也可以\(O(1)\)(因为原来的链表结构中当前节点就记录着其之前的前驱后继),但是动态加入操作至少要一个二分的\(log\)的复杂度。所以我们要尽可能避免动态加入。

因为没学过回滚莫队所以我的写法比较奇怪:设\(solve(l,r)\)表示正在解决左端点在块\(l\)内、右端点在块\(r\)内的询问,并且此时已经维护出块\(l\)左端点到块\(r\)的右端点的凸包链表并维护出答案。

此时对于左端点在块\(l\)内、右端点在块\(r\)内的询问,我们只需要把零散的部分减掉就可以得到答案,然后栈序撤销删除操作。

询问做完之后通过删除元素递归进\(solve(l+1,r)\)和\(solve(l,r-1)\)。记得重复的\(solve\)步骤不要做多遍。

#include<bits/stdc++.h>
using namespace std; int read(){
int a = 0; char c = getchar(); bool f = 0;
while(!isdigit(c)){f = c == '-'; c = getchar();}
while(isdigit(c)){
a = a * 10 + c - 48; c = getchar();
}
return f ? -a : a;
} #define int long long
const int _ = 1.5e5 + 7 , T = sqrt(_) + 10;
struct node{int P , S;}now[_]; struct query{int l , r , id;};
#define PII pair < int , int >
int N , M , id[_] , ans[_] , S; vector < query > qry[T][T];
PII pos[_]; long double ang[_]; bool vis[T][T]; int operator %(PII A , PII B){return A.first * B.second - A.second * B.first;}
int cnt = 0; void del(int x){
++cnt;
S = S - pos[x] % pos[now[x].S] - pos[now[x].P] % pos[x] + pos[now[x].P] % pos[now[x].S];
now[now[x].P].S = now[x].S; now[now[x].S].P = now[x].P;
} void add(int x){
++cnt;
S = S - pos[now[x].P] % pos[now[x].S] + pos[now[x].P] % pos[x] + pos[x] % pos[now[x].S];
now[now[x].P].S = x; now[now[x].S].P = x;
} void solve(int l , int r){
//cerr << l << ' ' << r << endl;
if(vis[l / T][r / T]) return;
vis[l / T][r / T] = 1;
for(auto t : qry[l / T][r / T]){
assert(t.l - l <= T && r - t.r <= T);
for(int i = l ; i < t.l ; ++i) del(i);
for(int i = r ; i > t.r ; --i) del(i);
ans[t.id] = S;
for(int i = t.r + 1 ; i <= r ; ++i) add(i);
for(int i = t.l - 1 ; i >= l ; --i) add(i);
} if(r - l > T){
int cur = l; do{del(l++);}while(l % T); solve(l , r); do{add(--l);}while(l != cur);
cur = r; do{del(r--);}while((r + 1) % T); solve(l , r); do{add(++r);}while(r != cur);
}
} signed main(){
N = read(); M = read();
for(int i = 0 ; i < N ; ++i){
pos[i].first = read(); pos[i].second = read();
id[i] = i; ang[i] = atan2(pos[i].second , pos[i].first);
}
sort(id , id + N , [&](int x , int y){return ang[x] < ang[y];});
for(int i = 0 ; i < N ; ++i){now[id[i]].P = id[i ? i - 1 : N - 1]; now[id[i]].S = id[i == N - 1 ? 0 : i + 1];}
for(int i = 1 ; i <= M ; ++i){int p = read() - 1 , q = read() - 1; qry[p / T][q / T].push_back((query){p , q , i});}
for(int i = 0 ; i < N ; ++i){S += pos[i] % pos[now[i].S];}
solve(0 , N - 1); for(int i = 1 ; i <= M ; ++i) printf("%lld\n" , ans[i]);
cerr << cnt << endl;
return 0;
}

最新文章

  1. JAVA面向对象-多态的理解
  2. 使用mutt+msmtp在Linux命令行界面下发邮件(续)
  3. Monkey测试4——Monkey命令行可用的全部选项
  4. MySQL-python模块
  5. Asp.net mvc中整合autofac
  6. 基于新浪sae使用php生成图片发布图文微博
  7. 如何给对话框中的控件发送消息呢?Windows消息分类
  8. [wikichip]zen架构图
  9. 面试必备:ArrayList源码解析(JDK8)
  10. STM32F103 ------ BOOT0 / BOOT1
  11. Windows10下Docker监控管理工具:Hyper-V管理器
  12. Flex学习笔记-Vgropu Hgroup 定义的组 表单程序。
  13. salesforce 零基础学习(六十三)Comparable实现Object列表数据的自定义排序
  14. Networking---poj1287最小生成树
  15. 微信小程序退款 处理类
  16. Wasserstein距离 和 Lipschitz连续
  17. [C语言] 数据结构-预备知识结构体
  18. Python--paramiko库:连接远程服务器操作文件
  19. C# 反射(Reflection)技术
  20. FTP文件上传以及获取ftp配置帮助类

热门文章

  1. python列表推导式及其简单应用
  2. JavaScript的Proxy可以做哪些有意思的事儿
  3. Linux内存含义
  4. 十八、Python面向对象之魔术方法
  5. HDU1754 &amp;&amp; HDU1166 线段树模板题
  6. vuex的简单总结使用
  7. linux 文件上传 linux服务器
  8. 【Hadoop】CDH、Presto配置问题
  9. pycharm运行过程中pycharm控制台和python控制台之间的切换
  10. 防御流类型的xss攻击