JZOJ 5618. 【NOI2018模拟3.31】华胥梦天
生活随笔
收集整理的這篇文章主要介紹了
JZOJ 5618. 【NOI2018模拟3.31】华胥梦天
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
Input
Output
Data Constraint
Solution
吉如一論文里的線段樹算法……
對于一個區間,記錄三個值:最大值 mx1,最大值的個數 cnt,嚴格次大值 mx2。
那么在一個區間內要修改為 x ,
如果有 x≥mx1 ,就不用修改,直接退出。
如果有 mx2≤x<mx1 ,則區間和 sum?=(mx1?x)?cnt ,再 mx1=x 即可。
如果 x<mx2 ,則直接遞歸左右子樹。
記得下傳標記,要隨時維護嚴格次大值。
時間復雜度通過勢能分析可得為 O(N?log?N) 。
Code
#include<cstdio> #include<cctype> using namespace std; typedef long long LL; const int N=5e5+5; struct data {int mx1,cnt,mx2;LL sum; }f[N<<2]; LL last; int qx,qy,qz; int a[N]; template<typename T>inline T read() {T X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline int max(int x,int y) {return x>y?x:y; } inline void update(int v) {int ls=v<<1,rs=ls|1;if(f[ls].mx1>f[rs].mx1){f[v].mx1=f[ls].mx1;f[v].cnt=f[ls].cnt;f[v].mx2=max(f[ls].mx2,f[rs].mx1);}elseif(f[ls].mx1<f[rs].mx1){f[v].mx1=f[rs].mx1;f[v].cnt=f[rs].cnt;f[v].mx2=max(f[rs].mx2,f[ls].mx1);}else{f[v].mx1=f[ls].mx1;f[v].cnt=f[ls].cnt+f[rs].cnt;f[v].mx2=max(f[ls].mx2,f[rs].mx2);}f[v].sum=f[ls].sum+f[rs].sum; } inline void modify(int v,int x) {if(x>=f[v].mx1) return;f[v].sum-=(LL)(f[v].mx1-x)*f[v].cnt;f[v].mx1=x; } inline void down(int v) {modify(v<<1,f[v].mx1);modify(v<<1|1,f[v].mx1); } void make(int v,int l,int r) {if(l==r){f[v].sum=f[v].mx1=a[l];f[v].cnt=1,f[v].mx2=-1;return;}int mid=l+r>>1;make(v<<1,l,mid);make(v<<1|1,mid+1,r);update(v); } void change(int v,int l,int r) {if(qz>=f[v].mx1) return;if(qx<=l && r<=qy && qz>f[v].mx2){modify(v,qz);return;}down(v);int mid=l+r>>1;if(qx<=mid) change(v<<1,l,mid);if(qy>mid) change(v<<1|1,mid+1,r);update(v); } LL find(int v,int l,int r) {if(qx<=l && r<=qy) return f[v].sum;int mid=l+r>>1;down(v);LL s=0;if(qx<=mid) s+=find(v<<1,l,mid);if(qy>mid) s+=find(v<<1|1,mid+1,r);update(v);return s; } int main() {int n=read<int>(),m=read<int>();for(int i=1;i<=n;i++) a[i]=read<int>();make(1,1,n);while(m--){int op=read<int>();qx=read<LL>()^last;qy=read<LL>()^last;if(op==1){int x=qy;qy=qx;int num=find(1,1,n);qz=max(num-x,0);change(1,1,n);}elseif(op==2){qz=read<LL>()^last;change(1,1,n);}else printf("%lld\n",last=find(1,1,n));}return 0; }總結
以上是生活随笔為你收集整理的JZOJ 5618. 【NOI2018模拟3.31】华胥梦天的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LOJ #516. 「LibreOJ β
- 下一篇: JZOJ 5616. 【NOI2018模