#loj3059 HNOI2019 序列
生活随笔
收集整理的這篇文章主要介紹了
#loj3059 HNOI2019 序列
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
據說是保序回歸問題?
業界都在用的算法是將序列分成若干段,然后每段取個平均值生成一個不降的b序列
至于為啥是對的?我也不知道啊
一開始想寫個主席樹
然后懶癌發作選擇了反復二分的咸魚做法
先考慮50分怎么做的,我們使用一個棧存儲所有的段,
然后每次插入一個段的時候保證單調棧中每一段全部是單調遞增的就ok了
提取一段的方差可以用平均數的平方減去平方的平均數來算
現在來考慮100分怎么搞
由于每次都是假如這個位置變成了xxx的修改,因此考慮將左側前綴和右側后綴的單調棧拼接在一起
將所有詢問離線,然后假定更改的元素不會引起右側單調棧的變化,然后嘗試將這個點插入到左側單調棧當中
使用二分而不是均攤的pop可以做到log的復雜度
此時我們得到了左側的段,然后假定此時我們得到的左邊界就是正確的,然后嘗試將這一整段插入到右側單調棧當中
借助二分法這一步的復雜度自然是log的
然后接著假定右側的邊界就是正確的邊界,那么以此為依據去二分左側
如此反復迭代若干次就可以得到正確的解了
局的這東西和單純形算法很像,都是隨機卡不掉但是構造就跪了的東西
但是事實上出題人為了卡掉僅僅二分一次的算法就竭盡全力的,所以迭代6,7次就能過了
#include<cstdio> #include<algorithm> #include<vector> using namespace std;const int N=1e5+10;typedef long long ll; typedef long double ld;const ll mod=998244353; ll inv[N];ll ansmid[N],ansleft[N],ansright[N]; int cur_round; inline void pre() {inv[0]=inv[1]=1;for(int i=2;i<N;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod; } struct data {ll cnt0;ll cnt1;ll cnt2;friend data operator +(data a,data b){return (data){a.cnt0+b.cnt0,a.cnt1+b.cnt1,(a.cnt2+b.cnt2)%mod};}friend data operator -(data a,data b){return (data){a.cnt0-b.cnt0,a.cnt1-b.cnt1,(a.cnt2+mod-b.cnt2)%mod};}friend bool operator <(data a,data b){if(cur_round)return (ld)(a.cnt1)/(a.cnt0)<(ld)(b.cnt1)/(b.cnt0);else return (ld)(a.cnt1)/(a.cnt0)>(ld)(b.cnt1)/(b.cnt0); }inline ll cval(){ll tval=cnt1%mod;(tval*=tval)%=mod;return (cnt2+tval*(mod-inv[cnt0]))%mod;} }st[N],sum[N];ll ansst[N];int tp;int n;int m; struct qry {int id;data tmp;data ori; }; vector <qry> vq[N];ll a[N]; inline void ins_ele(data tmp) {st[++tp]=tmp;while(tp>1&&st[tp]<st[tp-1])st[tp-1]=st[tp-1]+st[tp],tp--;sum[tp]=st[tp]+sum[tp-1];ansst[tp]=(st[tp].cval()+ansst[tp-1])%mod; } inline data fastpop(data qry,ll& mans,ll& mans2) {int l=0;int r=tp;while(l!=r){int mid=(l+r+1)>>1;if(st[mid]<(sum[tp]-sum[mid]+qry))l=mid;else r=mid-1;}mans2=(sum[tp]-sum[l]+qry).cval();mans=ansst[l];//printf("fast pop locte=%d %lld %lld\n",l,mans2,mans);return sum[tp]-sum[l]; } int main() {//freopen("mtst.in","r",stdin);pre();scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lld",&a[i]);cur_round=1;for(int i=1;i<=n;i++)ins_ele((data){1,a[i],(a[i]*a[i])%mod});printf("%lld\n",ansst[tp]);for(int i=1,u,k;i<=m;i++){scanf("%d%d",&u,&k);data nw=(data){1,k,(ll)k*k%mod};vq[u].push_back((qry){i,nw,nw});} for(int z=1;z<=20;z++){// printf("z=%d,front:\n",z);cur_round=1;tp=0;for(int i=1;i<=n;i++){for(vector <qry> :: iterator it=vq[i].begin();it!=vq[i].end();++it)it->tmp=it->ori+fastpop(it->tmp,ansleft[it->id],ansmid[it->id]);ins_ele((data){1,a[i],a[i]*a[i]%mod});}cur_round=0;// printf("z=%d,back:\n",z);tp=0;for(int i=n;i>=1;i--){for(vector <qry> :: iterator it=vq[i].begin();it!=vq[i].end();++it)it->tmp=it->ori+fastpop(it->tmp,ansright[it->id],ansmid[it->id]);ins_ele((data){1,a[i],a[i]*a[i]%mod});}}for(int i=1;i<=m;i++)printf("%lld\n",(ansleft[i]+ansmid[i]+ansright[i])%mod);return 0; }轉載于:https://www.cnblogs.com/sweetphoenix/p/10814987.html
總結
以上是生活随笔為你收集整理的#loj3059 HNOI2019 序列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库的增删改查的一个例题
- 下一篇: CoralGloba珊瑚跨境的“全银行通