BZOJ4826: [Hnoi2017]影魔(扫描线+树状数组)
来源:互联网 发布:java设计模式23种分类 编辑:程序博客网 时间:2024/04/28 12:39
传送门
题意:
有n个点,横纵坐标都是
(定义
1.
2.
题解:
离线扫描线+树状数组。
先单调栈找出左右第一个纵坐标大于
首先,对于第一种情况,设有
那么
证明:若不是,则两点间有一点纵坐标大于
对于第二种情况,容易发现所有情况都包含在了对于每个
然后把所有合法的点对看做点或者是线段。扫描线一遍即可。
(出题人丧心病狂的卡了线段树,所以学了树状数组的区间加减查询:http://www.cnblogs.com/lcf-2000/p/5866170.html#3773822)
#include<bits/stdc++.h>using namespace std;struct IO{ streambuf *ib,*ob; int buf[50]; inline void init() { ios::sync_with_stdio(false); cin.tie(NULL);cout.tie(NULL); ib=cin.rdbuf();ob=cout.rdbuf(); } inline int read() { char ch=ib->sbumpc();int i=0,f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();} while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();} return i*f; } inline void W(long long x) { if(!x){ob->sputc('0');return;} if(x<0){ob->sputc('-');x=-x;} while(x){buf[++buf[0]]=x%10,x/=10;} while(buf[0]){ob->sputc(buf[buf[0]--]+'0');} }}io;const int Maxn=2e5+50;int n,m,p1,p2,L[Maxn],R[Maxn],K[Maxn];long long ans[Maxn];struct Segment{ int l,r; Segment(int l,int r):l(l),r(r){}};inline int lowbit(int pos){return pos&(-pos);}struct BIT{ long long d1[Maxn],d2[Maxn]; inline long long asksum(int x) { long long res1=0,res2=0; for(int pos=x;pos;pos-=lowbit(pos))res1+=d1[pos],res2+=d2[pos]; return res1*(x+1)-res2; } inline long long query(int l,int r){return asksum(r)-asksum(l-1);} inline void modify(int l,int r) { for(int pos=l;pos<=n;pos+=lowbit(pos))d1[pos]++,d2[pos]+=l; for(int pos=r+1;pos<=n;pos+=lowbit(pos))d1[pos]--,d2[pos]-=(r+1); }}t1,t2;struct Q{ int l,r,id,bz; Q(int l=0,int r=0,int id=0,int bz=0):l(l),r(r),id(id),bz(bz){}};vector<Segment>data2[Maxn];vector<int>data[Maxn];vector<Q>query[Maxn];inline void GetL(int *a){ static int st[Maxn],pos[Maxn],tail; pos[1]=1,st[1]=K[1];tail=1; for(int i=2;i<=n;i++) { while(st[tail]<K[i]&&tail)a[pos[tail--]]=i; st[++tail]=K[i],pos[tail]=i; } while(tail)a[pos[tail--]]=n+1;}int main(){ io.init();n=io.read(),m=io.read(),p1=io.read(),p2=io.read(); for(int i=1;i<=n;i++)K[i]=io.read(); GetL(R);reverse(K+1,K+n+1); GetL(L);reverse(L+1,L+n+1); for(int i=1;i<=n;i++)L[i]=n-L[i]+1; for(int i=1;i<=n;i++) { if(L[i])data[i].push_back(L[i]); if(R[i]!=n+1)data[i].push_back(R[i]); if(L[i]&&R[i]>i+1)data2[L[i]].push_back(Segment(i+1,R[i]-1)); if(R[i]!=n+1&&L[i]<i-1)data2[R[i]].push_back(Segment(L[i]+1,i-1)); } for(int i=1;i<=m;i++) { int l=io.read(),r=io.read();l--; if(l)query[l].push_back(Q(l+1,r,i,-1)); query[r].push_back(Q(l+1,r,i,1)); } for(int i=1;i<=n;i++) { for(int e=data[i].size()-1;e>=0;e--)t1.modify(data[i][e],data[i][e]); for(int e=data2[i].size()-1;e>=0;e--)t2.modify(data2[i][e].l,data2[i][e].r); for(int e=query[i].size()-1;e>=0;e--) { ans[query[i][e].id]+=1ll*p1*query[i][e].bz*t1.query(query[i][e].l,query[i][e].r); ans[query[i][e].id]+=1ll*p2*query[i][e].bz*t2.query(query[i][e].l,query[i][e].r); } } for(int i=1;i<=m;i++)io.W(ans[i]),io.ob->sputc('\n');}
阅读全文
0 0
- BZOJ4826: [Hnoi2017]影魔(扫描线+树状数组)
- BZOJ4826:[Hnoi2017]影魔 (单调栈+扫描线+线段树)
- BZOJ4826 [Hnoi2017]影魔
- [bzoj4826][HNOI2017]影魔
- bzoj4826 [Hnoi2017]影魔
- bzoj4826 hnoi2017影魔
- BZOJ4826: [Hnoi2017]影魔
- BZOJ4826: [Hnoi2017]影魔
- 【BZOJ4826】【HNOI2017】影魔
- [题解]bzoj4826 HNOI2017 影魔
- [BZOJ4826][HNOI2017]影魔-单调栈-线段树
- 【bzoj4826】影魔(线段树+单调栈+扫描线)
- [单调栈 扫描线] BZOJ 4826 [Hnoi2017]影魔
- POJ 2464 Brownie Points II(树状数组+扫描线)
- hdu 1556 Color the ball (扫描线+树状数组)
- HDU 5862 Counting Intersections (扫描线+树状数组)
- HDU4331 Image Recognition 树状数组+扫描线
- poj3109 Inner Vertices 扫描线+树状数组
- RecyclerView的简单介绍和实现
- Noip提高组2015 Day1 T2 信息传递 tarjan
- 文章标题
- 字符串数组在输入的时候应该给\0预留一个位置,否则将在c++中无法输出,并且编译的时候回报错!!!
- 堆--优先级队列--topK问题
- BZOJ4826: [Hnoi2017]影魔(扫描线+树状数组)
- Spring初步了解
- Core Java Volume I 读书笔记---第五章: 继承
- 清除缓存
- 虚拟网卡驱动
- Java读写.properties文件实例,解决中文乱码问题
- 新闻BaseAdapter
- spring连接池配置
- 求链式表的表长