#23933: 珂朵莉樹


DE45A (一葉之秋)

學校 : 新北市立板橋高級中學
編號 : 68688
來源 : [1.172.131.82]
最後登入時間 :
2024-01-11 01:11:14
f583. 末日時在做什麼?有沒有空?要來吃串燒嗎? -- codeforces896C | From: [1.172.145.210] | 發表日期 : 2021-01-02 22:08

由於這題的測資是隨機生成

所以可以用一個叫珂朵莉樹的資料結構來維護

珂朵莉樹是一個用set來存相同值的區間

#define IT set<Node>::iterator

IT split(int pos){

IT iter=tr.lower_bound(Node(pos));

if(iter!=tr.end()&&iter->l==pos)return iter;

--iter;

int nl=iter->l,nr=iter->r,nval=iter->val;

tr.erase(iter);

tr.insert(Node{nl,pos-1,nval});

return tr.insert(Node{pos,nr,nval}).first;

}

void assign(int l,int r,int val){

IT iterr=split(r+1),iterl=split(l);

tr.erase(iterl,iterr);

tr.insert(Node(l,r,val));

}

以上是珂朵莉樹的核心

split(int pos)是把原來含有pos位置的節點分成兩部分

例如:(1,8)-->(1,3)、(4,8)

assign(int l,int r,int val)的作用是區間付值(如果沒有這個操作基本上就不能用珂朵莉樹)

接下來區間加值、區間第K小、區間X次方和模mod就暴力硬做就好了

區間加值:

void add(int l,int r,int val){

IT iterr=split(r+1),iterl=split(l);

for(IT i=iterl;i!=iterr;++i)i->val+=val;

}

區間第K小:

int cmp(IT x,IT y){return x->val<y->val;}

int rk(int l,int r,int k){

vector<IT>g;

IT iterr=split(r+1),iterl=split(l);

for (IT i=iterl;i!=iterr;++i)g.push_back(i);

sort(g.begin(),g.end(),cmp);

int o=0;

for(auto i:g){

o+=i->r-i->l+1;

if(o>=k)return i->val;

}

}

區間X次方和模mod:

int pow_mod(int a,int n,int loli){

a%=loli;

int ans=1;

while(n){

if(n&1)ans*=a,ans%=loli;

a*=a,a%=loli,n/=2;

}

return ans;

}

int sum(int l,int r,int x,int loli){

int ans=0;

IT iterr=split(r+1),iterl=split(l);

for(IT i=iterl;i!=iterr;++i)ans=(ans+pow_mod(i->val,x,loli)*(i->r-i->l+1))%loli;

return ans;

}

最後補上我看不懂的證明:
http://codeforces.com/blog/entry/56135?#comment-398940

阿如果你只是要抄答案的話:

#include<bits/stdc++.h>

#define IT set<Node>::iterator

#define int long long

using namespace std;

int seed,vmax,x,y,n,m,l,r,op;

struct Node{

int l,r;

mutable int val;

Node(int _l=0,int _r=0,int _val=0):l(_l),r(_r),val(_val){}

bool operator < (const Node &nt) const{return l<nt.l;}

};

set<Node>tr;

IT split(int pos){

IT iter=tr.lower_bound(Node(pos));

if(iter!=tr.end()&&iter->l==pos)return iter;

--iter;

int nl=iter->l,nr=iter->r,nval=iter->val;

tr.erase(iter);

tr.insert(Node{nl,pos-1,nval});

return tr.insert(Node{pos,nr,nval}).first;

}

void assign(int l,int r,int val){

IT iterr=split(r+1),iterl=split(l);

tr.erase(iterl,iterr);

tr.insert(Node(l,r,val));

}

void add(int l,int r,int val){

IT iterr=split(r+1),iterl=split(l);

for(IT i=iterl;i!=iterr;++i)i->val+=val;

}

int cmp(IT x,IT y){return x->val<y->val;}

int rk(int l,int r,int k){

vector<IT>g;

IT iterr=split(r+1),iterl=split(l);

for (IT i=iterl;i!=iterr;++i)g.push_back(i);

sort(g.begin(),g.end(),cmp);

int o=0;

for(auto i:g){

o+=i->r-i->l+1;

if(o>=k)return i->val;

}

}

int pow_mod(int a,int n,int loli){

a%=loli;

int ans=1;

while(n){

if(n&1)ans*=a,ans%=loli;

a*=a,a%=loli,n/=2;

}

return ans;

}

int sum(int l,int r,int x,int loli){

int ans=0;

IT iterr=split(r+1),iterl=split(l);

for(IT i=iterl;i!=iterr;++i)ans=(ans+pow_mod(i->val,x,loli)*(i->r-i->l+1))%loli;

return ans;

}

main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

cin>>n>>m;

for(int i=1;i<=n;++i)cin>>op,tr.insert(Node(i,i,op));

tr.insert(Node(n+1,n+1,0));

for(int i=1;i<=m;++i){

cin>>op>>l>>r>>x;

if(op==1)add(l,r,x);

else if(op==2)assign(l,r,x);

else if(op==3)cout<<rk(l,r,x)<<"\n";

else cin>>y,cout<<sum(l,r,x,y)<<"\n";

}

}

 
ZeroJudge Forum