当前位置:网站首页>A brief talk on cordola tree
A brief talk on cordola tree
2022-06-27 12:21:00 【lAWTYl】
Kodori tree
Kodori is the happiest girl in the world qwq!!!
About her name
The origin is here :C. Willem, Chtholly and Seniorious
Of course , l u o g u luogu luogu It's the same question on the paper :C. Willem, Chtholly and Seniorious
Simply put, it lets you design a data structure , You can do the following :
- Add a number to all the numbers in the interval
- Change all numbers in the interval to x x x
- Find the interval number k k k Small
- Output... For each number in the interval k k k Power sum module p p p, That is to say ( ∑ i = l r a i x ) m o d p (\sum\limits_{i = l}^r a_i^x) \mod p (i=l∑raix)modp
And the data of this problem is guaranteed to be random .
And this problem is the first one with Kodori tree Is the problem of positive solution , And the title of this problem is 《 What are you doing at the end of the day ? Are you free ? Can you save ?》 In the background of the heroine cortori , So this data structure is called Kodori tree 了 .
Algorithm analysis
See this topic , All we think of are segment trees , Tree array , The data structure of classical maintenance interval problem such as block . However, it seems that several operations in this problem are not easy to maintain with these normal data structures , So we need to introduce such a mysterious data structure .
First , We can clearly notice the The data is guaranteed to be random Because I made this sentence bold (bushi . And there is an operation called "all the trees in the interval become..." x x x ( Later, we call this operation interval flattening ), With this operation , The complexity of the Kodori tree is guaranteed .
Some properties
Why do you say that , This requires us to look at some properties of the data when the data is random .
First of all, let's consider , Randomly select two endpoints in an interval l , r l, r l,r What is the expected length of the selected interval . Suppose the interval length is n n n, Now we have 1 n \frac 1n n1 There is a chance that l = L l = L l=L, And then there is 1 n \frac 1n n1 The probability of r = R r = R r=R, So the contribution to expectation this time is 1 n 2 ∣ R − L + 1 ∣ \frac 1{n^2}|R - L + 1| n21∣R−L+1∣, So the expected length is :
E = 1 n 2 ∑ l = 1 n ∑ r = 1 n ∣ r − l + 1 ∣ = 1 n 2 ( ∑ l = 1 n ∑ r = 1 l − 1 ∣ r − l + 1 ∣ + ∑ l = 1 n ∑ r = l n ∣ r − l + 1 ∣ ) = 1 n 2 ( ∑ l = 1 n ∑ r = 1 l − 1 ( l − r − 1 ) + ∑ l = 1 n ∑ r = l n ( r − l + 1 ) ) = 1 n 2 ( ∑ l = 1 n ∑ r = 1 l − 1 l − ∑ l = 1 n ∑ r = 1 l − 1 r − ∑ l = 1 n ∑ r = 1 l − 1 1 + ∑ l = 1 n ∑ r = l n r − ∑ l = 1 n ∑ r = l n l + ∑ l = 1 n ∑ r = l n 1 ) = 1 n 2 ( ∑ l = 1 n l ( l − 1 ) − ∑ l = 1 n 1 2 l ( l − 1 ) − ∑ l = 1 n ( l − 1 ) + ∑ l = 1 n 1 2 ( l + n ) ( n − l + 1 ) − ∑ l = 1 n ( n − l + 1 ) l + ∑ l = 1 n ( n − l + 1 ) ) = 1 n 2 ( 1 2 ∑ l = 1 n ( l − 1 ) 2 + 1 2 ∑ l = 1 n ( n − l + 1 ) 2 ) = 1 2 n 2 ( ∑ l = 0 n − 1 l 2 + ∑ l = 1 n l 2 ) = 1 2 n 2 ( 2 ∑ l = 1 n l 2 − n 2 ) = 1 n 2 ∑ l = 1 n l 2 − 1 2 = n ( n + 1 ) ( 2 n + 1 ) 6 n 2 − 1 2 = 2 n 2 + 3 n + 1 6 n − 1 2 = n 3 + 1 6 n ≈ 1 3 n \begin{aligned} E = & \frac{1}{n^2}\sum_{l = 1}^n\sum_{r = 1}^n|r - l + 1| \\ = & \frac{1}{n^2} \left( \sum_{l = 1}^n \sum_{r = 1}^{l-1} |r - l + 1| + \sum_{l = 1}^n\sum_{r = l}^n |r - l + 1| \right) \\ = & \frac{1}{n^2} \left( \sum_{l = 1}^n \sum_{r = 1}^{l-1} (l - r - 1) + \sum_{l = 1}^n\sum_{r = l}^n (r - l + 1) \right) \\ = & \frac{1}{n^2} \left( \sum_{l = 1}^n\sum_{r = 1}^{l - 1}l - \sum_{l = 1}^n \sum_{r = 1}^{l - 1}r - \sum_{l = 1}^n\sum_{r = 1}^{l - 1}1 + \sum_{l = 1}^n\sum_{r = l}^nr - \sum_{l = 1}^n\sum_{r = l}^nl + \sum_{l = 1}^n\sum_{r = l}^n1 \right) \\ = & \frac{1}{n^2} \left( \sum_{l = 1}^nl(l-1) - \sum_{l=1}^n\frac{1}{2}l(l-1) - \sum_{l=1}^n(l-1) + \sum_{l=1}^n\frac{1}{2}(l + n)(n - l + 1) - \sum_{l=1}^n(n-l+1)l + \sum_{l=1}^n(n-l+1) \right) \\ = & \frac{1}{n^2} \left( \frac 12\sum_{l=1}^n(l-1)^2 + \frac 12\sum_{l=1}^n(n-l+1)^2 \right) = \frac{1}{2n^2} \left( \sum_{l=0}^{n-1}l^2 + \sum_{l=1}^nl^2 \right) = \frac{1}{2n^2} \left( 2\sum_{l = 1}^n l^2 - n^2 \right) = \frac{1}{n^2}\sum_{l=1}^nl^2 - \frac{1}{2} \\ = & \frac{n(n+1)(2n+1)}{6n^2} - \frac 12 = \frac{2n^2+3n+1}{6n} - \frac 12 = \frac n3 + \frac 1{6n} \\ \approx & \frac 13 n \end{aligned} E=======≈n21l=1∑nr=1∑n∣r−l+1∣n21(l=1∑nr=1∑l−1∣r−l+1∣+l=1∑nr=l∑n∣r−l+1∣)n21(l=1∑nr=1∑l−1(l−r−1)+l=1∑nr=l∑n(r−l+1))n21(l=1∑nr=1∑l−1l−l=1∑nr=1∑l−1r−l=1∑nr=1∑l−11+l=1∑nr=l∑nr−l=1∑nr=l∑nl+l=1∑nr=l∑n1)n21(l=1∑nl(l−1)−l=1∑n21l(l−1)−l=1∑n(l−1)+l=1∑n21(l+n)(n−l+1)−l=1∑n(n−l+1)l+l=1∑n(n−l+1))n21(21l=1∑n(l−1)2+21l=1∑n(n−l+1)2)=2n21(l=0∑n−1l2+l=1∑nl2)=2n21(2l=1∑nl2−n2)=n21l=1∑nl2−216n2n(n+1)(2n+1)−21=6n2n2+3n+1−21=3n+6n131n
in other words , Each interval flattening we expect will cover 1 3 \frac 13 31 The whole range of , This will make a large part of the numbers the same . So let's consider recording a continuous paragraph with the same number as a point ( Each point in the code will record a l , r , v a l l, r, val l,r,val, Respectively represent the same value of the left endpoint, the right endpoint and all numbers in this point ), Let's calculate the expected number of points after many interval flattening .
Obviously, we can guess that the number of points should be O ( log n ) O(\log n) O(logn) Grade , But proving this is a bit of a hassle .
We ask for the expected number of points , We first need to prove a lemma : Make p j p_j pj Indicates that the subscript is j j j The number of is now the endpoint of a point and is in progress k k k The probability that the sub interval is still the endpoint of a certain point after flattening , So there are 1 n ∑ j = 1 n = O ( 1 k ) \frac 1n\sum\limits_{j = 1}^n = O(\frac 1k) n1j=1∑n=O(k1).
obviously , Each interval leveling operation does not cover a point j j j The probability of :
p j k = ( j − 1 ) 2 + ( n − j ) 2 n 2 \sqrt[k]{p_j} = \frac{(j-1)^2+(n-j)^2}{n^2} kpj=n2(j−1)2+(n−j)2
That is to say, both points are selected in j j j The probability before the point plus two points is selected at j j j Probability after point , Then the formula to be proved above can be written as :
1 n ∑ j = 1 n = 1 n ∑ j = 1 n ( j − 1 ) 2 + ( n − j ) 2 n 2 \frac 1n\sum_{j = 1}^n = \frac 1n \sum_{j = 1}^n\frac{(j - 1)^2 + (n - j)^2}{n^2} n1j=1∑n=n1j=1∑nn2(j−1)2+(n−j)2
Change a dollar , Make x = j n x = \frac jn x=nj, There is :
p j = ( j 2 − 2 j + 1 n 2 + n 2 + j 2 − 2 n j n 2 ) k = ( x 2 − 2 n x + 1 n 2 + 1 + x 2 − 2 x ) k = ( x 2 − 2 x + 1 + x 2 − 2 j − 1 n 2 ) k ≤ ( x 2 + ( x − 1 ) 2 ) k \begin{aligned} p_j = & (\frac{j^2 - 2j + 1}{n^2} + \frac{n^2 + j^2 - 2nj}{n^2})^k \\ = & (x^2 - \frac 2nx + \frac 1{n^2} + 1 + x^2 - 2x)^k \\ = & (x^2 - 2x + 1 + x^2 - \frac {2j-1}{n^2})^k \\ \leq & (x^2 + (x - 1)^2 )^k \end{aligned} pj===≤(n2j2−2j+1+n2n2+j2−2nj)k(x2−n2x+n21+1+x2−2x)k(x2−2x+1+x2−n22j−1)k(x2+(x−1)2)k
Bring it into the whole equation , Namely :
1 n ∑ j = 1 n p j ≤ ∑ j = 1 n ( x 2 + ( x − 1 ) 2 ) k ≈ ∫ 0 1 ( x 2 + ( x − 1 ) 2 ) k d x \frac 1n \sum_{j = 1}^np_j \leq \sum_{j = 1}^n(x^2+(x-1)^2)^k \approx \int_0^1 (x^2 + (x - 1)^2)^k dx n1j=1∑npj≤j=1∑n(x2+(x−1)2)k≈∫01(x2+(x−1)2)kdx
Then you can use a calculator or manual integration , So we can get the upper bound of this equation O ( 1 k ) O(\frac 1k) O(k1).
With this formula , We can know that the probability that each point in all the initial endpoints will still exist in the end is, on average O ( 1 k ) O(\frac 1k) O(k1). With this, we can naturally deduce the interval expectation points :
E ( m ) = O ( n ⋅ 1 k + ∑ i = 1 k 1 i ) = O ( n k + log k ) E(m) = O(n \cdot \frac 1k + \sum_{i = 1}^k \frac 1i) = O(\frac nk + \log k) E(m)=O(n⋅k1+i=1∑ki1)=O(kn+logk)
That is to say, there was n n n A little bit , The probability that each point will still exist in the end is 1 k \frac 1k k1, Then the expected number of these points is n k \frac nk kn, Then on the penultimate i i i New... Will be created in this operation O ( 1 ) O(1) O(1) A little bit , So these points are in the rest i i i The probability of remaining after the first operation is O ( 1 i ) O(\frac 1i) O(i1), So the contribution of the new point is ∑ i = 1 k 1 i \sum\limits_{i = 1}^k \frac 1i i=1∑ki1.
And then it's over !!!
To test whether our proof is correct , We can write a piece of code to verify :
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
#define MAXN 100100000
#define MOD 1000000007
struct Tnode{
int l, r;
mutable int v;
Tnode(int l, int r = 0, int v = 0) : l(l), r(r), v(v) {
}
bool operator < (const Tnode &rhs) const {
return l < rhs.l; }
};
int n = 0;
int a[MAXN] = {
0 };
set<Tnode> s;
set<Tnode> :: iterator split(int pos){
set<Tnode> :: iterator it = s.lower_bound(Tnode(pos));
if(it != s.end() and it->l == pos) return it;
it--;
if(it->r < pos) return s.end();
int l = it->l, r = it->r, v = it->v;
s.erase(it);
s.insert(Tnode(l, pos - 1, v));
return s.insert(Tnode(pos, r, v)).first;
}
void assign(int l, int r, int x){
set<Tnode> :: iterator ir = split(r + 1), il = split(l);
s.erase(il, ir);
s.insert(Tnode(l, r, x));
}
signed main(){
n = 1000000; srand(time(0));
for(int i = 1; i <= n; i++){
a[i] = rand() * rand() % n + 1;
s.insert(Tnode(i, i, a[i]));
}
for(int i = 1; i <= n; i++){
int l = rand() * rand() % n + 1;
int r = rand() * rand() % n + 1;
int x = rand() * rand() % n + 1;
if(l > r) swap(l, r);
assign(l, r, x);
}
cout << s.size() << '\n';
return 0;
}
In code s p l i t ( ) split() split() and a s s i g n ( ) assign() assign() The working principle of is described in detail below , I won't repeat it here .
We use this code to run 10 10 10 Average the times , stay n = 1 e 6 n = 1e6 n=1e6 when , The number of points is stable at 20 ∼ 30 20\sim30 20∼30 Between , It is in good agreement with the theoretical value , This further proves that our proof is correct .
Now let's look at the operation
Now we know that our points are O ( log n ) O(\log n) O(logn) Level , Now we can naturally think of using these points to partition , If we can make the time complexity of the operation of each section as O ( 1 ) O(1) O(1) Then we can do O ( n log n ) O(n\log n) O(nlogn) Time to solve this problem ( But in fact, the complexity of maintaining a single operation here is O ( log n ) O(\log n) O(logn) Of ). Specifically, we maintain :
First create a structure :
struct Tnode{
int l, r;
mutable int v;
Tnode(int l, int r = 0, int v = 0) : l(l), r(r), v(v) {
}
bool operator < (const Tnode &rhs) const {
return l < rhs.l; }
};
One of this structure “ spot ” There are three data in l , r l, r l,r and v v v, It respectively represents the left end point and the right end point in this continuous interval , The same number as all the numbers in this paragraph . And then here's m u t a b l e mutable mutable Keyword means that we can directly modify the inserted s e t set set The elements of the v v v value , Instead of taking the element out and adding it back s e t set set.
And then another one s e t set set To maintain the entire section :
set<Tnode> s;
In this way, we have an empty Kodori tree . Yes , It's that simple qwq.
Then there are several important operations .
split
This operation allows us to include the original point p o s pos pos The range of [ l , r ] [l, r] [l,r] Divide into [ l , p o s − 1 ] [l, pos - 1] [l,pos−1] and [ p o s , r ] [pos, r] [pos,r] These two intervals , And return the iterator of the latter .
Let's use l o w e r _ b o u n d ( ) lower\_bound() lower_bound() Function in s e t set set It is found that the position of the left end point is greater than or equal to pos The node of . If the left endpoint of this node is exactly pos, Then we don't need to split , Go straight back to . If its left endpoint position is not p o s pos pos, Then it must be greater than p o s pos pos, Contains the location pos The node of is the previous node , i t − = 1 it-=1 it−=1. The rest is easy , Violent split and then insert . Don't forget to return the value .
set<Tnode> :: iterator split(int pos){
set<Tnode> :: iterator it = s.lower_bound(Tnode(pos)); // Find the left endpoint greater than or equal to pos The range of
if(it != s.end() and it->l == pos) return it; // If the left end of this point is pos You don't have to split Just go straight back
it--; // The left endpoint is not pos That's more than pos, contain pos It must be the previous point
if(it->r < pos) return s.end();
int l = it->l, r = it->r, v = it->v;
s.erase(it); // Violent deletion
s.insert(Tnode(l, pos - 1, v)); // Add a little violence
return s.insert(Tnode(pos, r, v)).first; // Violence plus points plus returns
}
assign
This is the most important operation to reduce complexity in the Kodori tree : Interval leveling . Because the implementation of this operation is too simple , So just look at the code :
void assign(int l, int r, int x){
set<Tnode> :: iterator ir = split(r + 1), il = split(l); // hold l Between people split Into a whole paragraph
s.erase(il, ir); // Delete all the nodes in the middle
s.insert(Tnode(l, r, x)); // Create a new node and insert it
}
The rest is violence and fragmentation , Let's not go into details . The complete code is posted below :
End of the flower !!!
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
#define MAXN 100100
#define MOD 1000000007
struct Tnode{
int l, r;
mutable int v;
Tnode(int l, int r = 0, int v = 0) : l(l), r(r), v(v) {
}
bool operator < (const Tnode &rhs) const {
return l < rhs.l; }
};
int n = 0; int m = 0;
int seed = 0; int vmax = 0;
int a[MAXN] = {
0 };
set<Tnode> s;
set<Tnode> :: iterator split(int pos){
set<Tnode> :: iterator it = s.lower_bound(Tnode(pos));
if(it != s.end() and it->l == pos) return it;
it--;
if(it->r < pos) return s.end();
int l = it->l, r = it->r, v = it->v;
s.erase(it);
s.insert(Tnode(l, pos - 1, v));
return s.insert(Tnode(pos, r, v)).first;
}
void add(int l, int r, int x) {
set<Tnode>::iterator ir = split(r + 1), il = split(l);
for (set<Tnode>::iterator it = il; it != ir; ++it) it->v += x;
}
void assign(int l, int r, int x){
set<Tnode> :: iterator ir = split(r + 1), il = split(l);
s.erase(il, ir);
s.insert(Tnode(l, r, x));
}
struct Trank{
int num, cnt;
bool operator < (const Trank & rhs) const {
return num < rhs.num; }
Trank(int num, int cnt) : num(num), cnt(cnt) {
}
};
int rk(int l, int r, int x){
set<Tnode> :: iterator ir = split(r + 1), il = split(l);
vector<Trank> v;
for(set<Tnode> :: iterator i = il; i != ir; i++)
v.push_back(Trank(i->v, i->r - i->l + 1));
sort(v.begin(), v.end());
int i = 0;
for(i = 0; i < v.size(); i++)
if(v[i].cnt < x) x -= v[i].cnt;
else break;
return v[i].num;
}
int power(int x, int y, int p){
int r = 1, base = x % p;
while(y){
if(y & 1) r = r * base % p;
base = base * base % p;
y >>= 1;
}
return r;
}
int calp(int l, int r, int x, int y){
set<Tnode> :: iterator ir = split(r + 1), il = split(l);
int ans = 0;
for(set<Tnode> :: iterator i = il; i != ir; i++)
ans = (ans + power(i->v, x, y) * (i->r - i->l + 1) % y) % y;
return ans;
}
int rd(){
int res = seed;
seed = (seed * 7 + 13) % MOD;
return res;
}
signed main(){
cin >> n >> m >> seed >> vmax;
for(int i = 1; i <= n; i++){
a[i] = (rd() % vmax) + 1;
s.insert(Tnode(i, i, a[i]));
}
for(int i = 1; i <= m; i++){
int op = (rd() % 4) + 1;
int l = (rd() % n) + 1;
int r = (rd() % n) + 1;
if(l > r) swap(l, r);
if(op == 1){
int x = (rd() % vmax) + 1;
add(l, r, x);
}
else if(op == 2){
int x = (rd() % vmax) + 1;
assign(l, r, x);
}
else if(op == 3){
int x = (rd() % (r - l + 1)) + 1;
cout << rk(l, r, x) << '\n';
}
else{
int x = (rd() % vmax) + 1;
int y = (rd() % vmax) + 1;
cout << calp(l, r, x, y) << '\n';
}
}
return 0;
}
边栏推荐
- Hands on API development
- Online bidding of Oracle project management system
- R语言使用MASS包的polr函数构建有序多分类logistic回归模型、使用VGAM包的vglm函数对有序多分类logistic回归模型进行平行性假设作检验
- i. Construction of mx6ull C language environment
- Drive to APasS!使用明道云管理F1赛事
- Microservice splitting
- Nifi from introduction to practice (nanny level tutorial) - identity authentication
- Unlock the secret of C language key words (issue 6)
- Thymeleaf的相关知识
- Hibernate operation Oracle database primary key auto increment
猜你喜欢

TiDB 6.0:让 TSO 更高效丨TiDB Book Rush

On ticheck

Safe landing practice of software supply chain under salesforce containerized ISV scenario

Interview shock 60: what will cause MySQL index invalidation?
![Dynamic programming [III] (interval DP) stone merging](/img/a4/82c4d63b8df5d092a96b80dd497147.jpg)
Dynamic programming [III] (interval DP) stone merging

Raspberry pie 3b+ learning

What is the TCP 3-time handshake process?

Histrix工作原理

1. Mx6ull startup mode

最短编辑距离(线性dp写法)
随机推荐
Drive to APasS!使用明道云管理F1赛事
Mybaitis generator details
深入理解 happens-before 原则
Peak store app imitation station development play mode explanation source code sharing
Mathematical knowledge -- ideas and examples of game theory (bash game, Nim game, wizov game)
优博讯出席OpenHarmony技术日,全新打造下一代安全支付终端
alibaba jarslink
Wechat applet payment password input
Interview shock 60: what will cause MySQL index invalidation?
57. The core principle of flutter - layout process
Getting started with go web programming: validators
Uni app sends request instructions using the escook / request miniprogram plug-in
application.properties 的配置信息
私藏干货分享:关于企业架构中如何进行平台化
【TcaplusDB知识库】TcaplusDB-tcapsvrmgr工具介绍(二)
Hands on API development
Interview shock 60: what will cause MySQL index invalidation?
数学知识——博弈论(巴什博奕、尼姆博奕、威佐夫博奕)思路及例题
如何修改 node_modules 裏的文件
聊聊 Go 语言与云原生技术