1. 程式人生 > 實用技巧 >LG P6749 『MdOI R3』Yoshino

LG P6749 『MdOI R3』Yoshino

Description

Yoshino 給了你一個長度為$n$的序列,第$i$項為 $a_i$

現在 Yoshino 會對數列進行 $m$次操作。

操作分成兩種:

  • $1\ l\ r\ x$Yoshino 把數列下標在 $[l,r]$區間內的數修改為了一個從 $x$開始公差為 $1$的等差數列。
  • $2$ Yoshino 需要查詢整個數列中的逆序對個數。逆序對的定義為數對 $(i,j)$滿足$i < j$且 $a_i > a_j$

Solution

考慮每次修改對答案產生的貢獻,於是開始時用樹狀陣列先統計初始的答案

每次的修改區間內部不會產生影響,考慮對修改區間兩側的數產生的影響

用陣列記錄對於修改區間中的數,修改區間前面的部分中有多少數大於第$i$位上的數,對其差分

用陣列記錄對於修改區間後面的部分,有多少修改區間中的數大於$i$,對其差分

每次更新陣列和答案即可

雖然複雜度不對但是可過

正解:線段樹套珂朵莉樹

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma
GCC optimize("-ftree-pre") #pragma GCC optimize("-ftree-vrp") #pragma GCC optimize("-fpeephole2") #pragma GCC optimize("-ffast-math") #pragma GCC optimize("-fsched-spec") #pragma GCC optimize("unroll-loops") #pragma GCC optimize("-falign-jumps") #pragma GCC optimize("-falign-loops") #pragma GCC optimize("-falign-labels") #pragma
GCC optimize("-fdevirtualize") #pragma GCC optimize("-fcaller-saves") #pragma GCC optimize("-fcrossjumping") #pragma GCC optimize("-fthread-jumps") #pragma GCC optimize("-funroll-loops") #pragma GCC optimize("-fwhole-program") #pragma GCC optimize("-freorder-blocks") #pragma GCC optimize("-fschedule-insns") #pragma GCC optimize("inline-functions") #pragma GCC optimize("-ftree-tail-merge") #pragma GCC optimize("-fschedule-insns2") #pragma GCC optimize("-fstrict-aliasing") #pragma GCC optimize("-fstrict-overflow") #pragma GCC optimize("-falign-functions") #pragma GCC optimize("-fcse-skip-blocks") #pragma GCC optimize("-fcse-follow-jumps") #pragma GCC optimize("-fsched-interblock") #pragma GCC optimize("-fpartial-inlining") #pragma GCC optimize("no-stack-protector") #pragma GCC optimize("-freorder-functions") #pragma GCC optimize("-findirect-inlining") #pragma GCC optimize("-fhoist-adjacent-loads") #pragma GCC optimize("-frerun-cse-after-loop") #pragma GCC optimize("inline-small-functions") #pragma GCC optimize("-finline-small-functions") #pragma GCC optimize("-ftree-switch-conversion") #pragma GCC optimize("-foptimize-sibling-calls") #pragma GCC optimize("-fexpensive-optimizations") #pragma GCC optimize("-funsafe-loop-optimizations") #pragma GCC optimize("inline-functions-called-once") #pragma GCC optimize("-fdelete-null-pointer-checks") #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m,a[30005],bits[30005],cnt[30005],ans,great[30005],sav[30005],maxx,L[30005],R[30005],X[30005],O[30005]; inline int read() { int w=0,f=1; char ch=0; while(ch<'0'||ch>'9') { ch=getchar(); } while(ch>='0'&&ch<='9') { w=(w<<1)+(w<<3)+ch-'0'; ch=getchar(); } return w*f; } inline void write(int x) { if(x>9) { write(x/10); } putchar(x%10+'0'); } inline void add(int pos) { while(pos<=maxx) { bits[pos]++; pos+=pos&-pos; } } inline int query(int pos) { int ret=0; while(pos) { ret+=bits[pos]; pos-=pos&-pos; } return ret; } int main() { n=read(); m=read(); for(register int i=1;i<=n;i++) { a[i]=read(); maxx=max(maxx,a[i]); } for(register int i=1;i<=n;i++) { cnt[i]=i-1-query(a[i]); ans+=cnt[i]; add(a[i]); } for(register int i=1;i<=m;i++) { O[i]=read(); if(O[i]==1) { L[i]=read(); R[i]=read(); X[i]=read(); maxx=max(maxx,X[i]+R[i]-L[i]); } } for(register int i=1;i<=m;i++) { int opt=O[i]; if(opt==1) { for(int j=0;j<=maxx;j++) { great[j]=sav[j]=0; } int l=L[i],r=R[i],x=X[i],vr=x+r-l; for(register int j=l;j<=r;j++) { ans-=cnt[j]; ++sav[a[j]-1]; a[j]=x+j-l; } for(register int j=1;j<l;j++) { if(a[j]>vr) { ++great[vr]; } else { ++great[a[j]-1]; } } for(register int j=vr;j>=x;j--) { great[j]+=great[j+1]; ans+=great[j]; cnt[j-x+l]=great[j]; } for(register int j=maxx;j;j--) { sav[j]+=sav[j+1]; } for(register int j=r+1;j<=n;j++) { cnt[j]-=sav[a[j]]; ans-=sav[a[j]]; cnt[j]+=max(0,min(vr-a[j],vr-x+1)); ans+=max(0,min(vr-a[j],vr-x+1)); } } else { write(ans); printf("\n"); } } return 0; }
Yoshino