[JZOJ5073]【GDOI2017第三轮模拟day1】影魔
来源:互联网 发布:为什么淘宝没有电棒 编辑:程序博客网 时间:2024/06/11 02:35
题目描述
有一个长度为n的排列a[],定义一个点对(i,j) (i < j)的贡献:
- 若
max(a[i+1 j−1])<min(a[i],a[j]) ,贡献p1 - 若
sort(a[i],a[j],max(a[i+1 j−1])) 后,max(a[i+1 j−1]) 为第二项,贡献p2
给m个询问,每次询问一个区间[l,r]的贡献和。
30%:1<= n,m <= 500。
另30%: p1=2*p2。
100%:1 <= n,m <= 200000;1 <= p1,p2 <= 1000。
分析
我们可以先从第二档分析一下。
p1=2*p2提示我们拆开p1,把情况1转化为2,怎么弄呢?
先看看情况2吧。考虑i作为左端点(右端点相似),对于一个点对(i,j),如果这
那么做法出来了:
对于i作为左端点。
1. 用单调栈弄出每一个点i向右跳的第一个比他大的点,记为next[i];
2. 离线挂询问从右到左扫,把点i为左端点的贡献记在右端点上,即线段树给[i+1,next[i]]打上+p2标记。
3. 对于左端点在i的询问(l,r),查询[l,r]的权值和。
4. i为右端点的话就翻转所有下标再做一次就好了。
那么满分怎么做呢?考虑到(i,next[i])构成了贡献p1的点对,而又被加了两次的p2,那么用刚刚的算法,每次做到i,就给贡献数组的next[i]那一位加上p1-2*p2,注意到同一点对p1不会加两次。
代码
#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<map>using namespace std;typedef long long ll;typedef double db;#define fo(i,j,k) for(i=j;i<=k;i++)#define fd(i,j,k) for(i=j;i>=k;i--)const int N=200010;struct rec{ int l,r,id;}que[N];struct seg{ ll sum,tag;}tr[N*4];int n,m,p1,p2,a[N],k,l[N],r[N],next[N],sta[N],st,le,i,j;ll prt[N];bool cmp(rec a,rec b){ return a.l>b.l;}void down(int x,int l,int r){ int m=(l+r)/2; tr[x].sum+=tr[x].tag*((ll)r-l+1); if (l!=r) { tr[x*2].tag+=tr[x].tag; tr[x*2+1].tag+=tr[x].tag; } tr[x].tag=0;}void change(int x,int l,int r,int i,int j,int val){ if (i>j) return; int m=(l+r)/2; down(x,l,r); if (l!=r) { down(x*2,l,m); down(x*2+1,m+1,r); } if (l==i&&r==j) { tr[x].tag+=val; down(x,l,r); return; } if (j<=m) change(x*2,l,m,i,j,val);else if (m<i) change(x*2+1,m+1,r,i,j,val);else { change(x*2,l,m,i,m,val); change(x*2+1,m+1,r,m+1,j,val); } tr[x].sum=tr[x*2].sum+tr[x*2+1].sum;}ll get(int x,int l,int r,int i,int j){ if (i>j) return 0; int m=(l+r)/2; down(x,l,r); if (l!=r) { down(x*2,l,m); down(x*2+1,m+1,r); } if (l==i&&r==j) return tr[x].sum; if (j<=m) return get(x*2,l,m,i,j);else if (m<i) return get(x*2+1,m+1,r,i,j);else return get(x*2,l,m,i,m)+get(x*2+1,m+1,r,m+1,j); tr[x].sum=tr[x*2].sum+tr[x*2+1].sum; }void solve(){ fo(i,1,m) que[i].l=l[i],que[i].r=r[i],que[i].id=i; sort(que+1,que+1+m,cmp); a[n+1]=1e9; sta[(st=1)]=n+1; fd(i,n,1) { while (st&&a[sta[st]]<a[i]) st--; next[i]=sta[st]; sta[++st]=i; } le=1; fd(i,n,1) { change(1,1,n+1,i+1,next[i],+p2); change(1,1,n+1,next[i],next[i],p1-2*p2); while (le<=m&&que[le].l==i) { prt[que[le].id]+=get(1,1,n+1,i,que[le].r); le++; } if (le>m) break; }}int main(){ freopen("sf.in","r",stdin);// freopen("sf.out","w",stdout); scanf("%d %d %d %d",&n,&m,&p1,&p2); fo(i,1,n) scanf("%d",a+i); fo(i,1,m) scanf("%d %d",l+i,r+i); solve(); fo(i,1,(n+1)*4) tr[i].sum=tr[i].tag=0; fo(i,1,n/2) swap(a[i],a[n-i+1]); fo(i,1,m) { l[i]=n-l[i]+1,r[i]=n-r[i]+1; swap(l[i],r[i]); } solve(); fo(i,1,m) printf("%lld\n",prt[i]);}
0 0
- [JZOJ5073]【GDOI2017第三轮模拟day1】影魔
- 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔
- 【jzoj5073】【GDOI2017第三轮模拟day1】【影魔】【数据结构】
- 【GDOI2017第三轮模拟day1】影魔(主席树)
- JZOJ 【GDOI2017第三轮模拟day1】单旋
- 【jzoj5072】【GDOI2017第三轮模拟day1】【单旋】【数据结构】
- [JZOJ5072]【GDOI2017第三轮模拟day1】单旋
- GDOI2017第三轮模拟总结
- GDOI2017第三轮模拟总结
- GDOI2017模拟第三轮总结
- 【GDOI2017第二轮模拟day1】最长路径
- 【GDOI2017第二轮模拟day1】公路建设
- 【JZOJ5060】【GDOI2017第二轮模拟day1】公路建设
- 【JZOJ5077】【GDOI2017第三轮模拟day2】树的难题
- 【JZOJ5078】【GDOI2017第三轮模拟day2】魔法咒语
- 【jzoj5060】【GDOI2017第二轮模拟day1】【公路建设】【数据结构】
- 【JZOJ5061】【GDOI2017第二轮模拟day1】最长路径
- 【jzoj5078】【GDOI2017第三轮模拟day2】【魔法咒语】【ac自动机】【矩阵快速幂】
- Android动画之ViewAnimation(TweenAnimation)视图动画(补间动画)
- 数组
- apache集成weblogic,Cannot open TEMP post file问题
- 翻转二叉树
- Hadoop MapReduce 在某一列上自连接(self join)
- [JZOJ5073]【GDOI2017第三轮模拟day1】影魔
- Neural Module Networks
- 配置伪分布式时的问题”JAVA_HOME is not set and could not be found“解决方法
- redis.conf 常用配置文件详解
- 数据库基础知识7
- 题目1154:Jungle Roads
- 欢迎使用CSDN-markdown编辑器
- 【一步一个脚印】Tomcat+MySQL为自己的APP打造服务器(3-3)Json数据交互
- 使用virtualenv和virtualenvwrapper