Preface difficulty will be roughly sorted not to write a summary of hip-hop for people who have just learned the line tree (practicing like me)
/* if you can't see the repay Why not just work step by step rubbish is relaxed to ljq */ #include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <cmath> #include <map> #include <stack> #include <set> #include <sstream> #include <vector> #include <stdlib.h> #include <algorithm> using namespace std; #define dbg(x) cout<<#x<<" = "<< (x)<< endl #define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl #define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl #define max3(a,b,c) max(a,max(b,c)) #define min3(a,b,c) min(a,min(b,c)) #define lc (rt<<1) #define rc (rt<<11) #define mid ((l+r)>>1) typedef pair<int,int> pll; typedef long long ll; const int inf = 0x3f3f3f3f; const int _inf = 0xc0c0c0c0; const ll INF = 0x3f3f3f3f3f3f3f3f; const ll _INF = 0xc0c0c0c0c0c0c0c0; const ll mod = (int)1e9+7; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} ll ksm(ll a,ll b,ll mod){int ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b>>=1;}return ans;} ll inv2(ll a,ll mod){return ksm(a,mod-2,mod);} void exgcd(ll a,ll b,ll &x,ll &y,ll &d){if(!b) {d = a;x = 1;y=0;}else{exgcd(b,a%b,y,x,d);y-=x*(a/b);}}//printf("%lld*a + %lld*b = %lld\n", x, y, d);
Here's the header for the following topic
001.CF1041C Simple Line Segment Tree Application
It means that nnn cup coffee has mmm hours working time every day. After drinking a cup of coffee, you have to wait for ddd time before you can drink a cup of coffee.
Ask how you arrange to minimize the number of days you have to finish all your coffee.
Practice directly on the greedy set on two points, but in line with the level of practicing their own line segment tree to write a line segment tree
(Forget _______________
Line segment tree is mainly update d by single point modification
Maximum query of interval query
The leftmost subscript query whose query is greater than or equal to x_
We just need to order the coffee time from the smallest coffee time to the number of days cnt and find the smallest one that is larger than his time + d.
const int MAX_N = 200025; struct node { ll a; int id; bool operator< (const node other) const { return a < other.a; } }arr[MAX_N]; int ans[MAX_N],cnt; ll maxx[MAX_N<<2]; int n,m,d; void up(int rt) { maxx[rt] = max(maxx[rt<<1],maxx[rt<<1|1]); } void build(int rt,int l,int r) { if(l==r) { maxx[rt] = arr[l].a; return ; } int mid = (l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x) { if(l==r) { maxx[rt] = 0; return; } int mid = (l+r)>>1; if(x<=mid) update(rt<<1,l,mid,x); else update(rt<<1|1,mid+1,r,x); up(rt); } ll query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) return maxx[rt]; int mid = (l+r)>>1; ll maxx1 = 0,maxx2 = 0; if(x<=mid) maxx1 = query(rt<<1,l,mid,x,y); if(mid<y) maxx2 = query(rt<<1|1,mid+1,r,x,y); return max(maxx1,maxx2); } int query_(int rt,int l,int r,ll x) { if(l==r) { return l; } int mid = (l+r)>>1; if(maxx[rt<<1]>=x) return query_(rt<<1,l,mid,x); else return query_(rt<<1|1,mid+1,r,x); } void solve(int i) { if(i>n) return; ans[arr[i].id] = cnt; ll tmp_ = arr[i].a; update(1,1,n,i); ll tmp = query(1,1,n,i,n); if(tmp>tmp_ + d) { int xb = query_(1,1,n,tmp_+d+1); ans[arr[xb].id] = cnt; solve(xb); } else return; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); cnt = 1; scanf("%d%d%d",&n,&m,&d); memset(ans,-1,sizeof(ans)); for(int i = 1;i<=n;++i) scanf("%lld",&arr[i].a),arr[i].id = i; sort(arr+1,arr+1+n); build(1,1,n); for(int i = 1;i<=n;++i) { if(ans[arr[i].id]!=-1) continue; else { ll tmp = query(1,1,n,i,n); if(tmp>arr[i].a+d) { solve(i); } else ans[arr[i].id] = cnt,update(1,1,n,i); cnt++; } } printf("%d\n",cnt-1); for(int i = 1;i<=n;++i) i==n?printf("%d\n",ans[i]):printf("%d ",ans[i]); //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
002.P4588
The initial value of the title is 1. Give you QQQ operations 1x 1 x1x. The operation represents multiplying x 2x 2 x to remove this value from the value of the iii operation.
In this way, we build a line segment tree with query sequence, which can be accomplished by update and up only.
Each output S[1]
const int MAX_N = 100025; ll s[MAX_N<<2]; ll arr[MAX_N]; void up(int rt) { s[rt] = s[rt<<1]*s[rt<<1|1]%MOD; } void build(int rt,int l,int r) { if(l==r) { s[rt] = 1; return ; } int mid = (l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v) { if(l==r) { s[rt] = v; return ; } int mid = (l+r)>>1; if(x<=mid) update(rt<<1,l,mid,x,v); else update(rt<<1|1,mid+1,r,x,v); up(rt); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t,Q,opt; scanf("%d",&t); while(t--) { scanf("%d%lld",&Q,&MOD); build(1,1,Q); for(int i = 1;i<=Q;++i) { scanf("%d%lld",&opt,&arr[i]); if(opt==1) arr[i]%=MOD,update(1,1,Q,i,arr[i]),printf("%lld\n",s[1]); else { update(1,1,Q,arr[i],1); printf("%lld\n",s[1]); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
003.FZU 2105
Mean of the title ANDANDAND 0 means that the interval assigns 000_1| 1_1, or 111 XOR 1 XOR 1 XOR 1 is the interval inversion
Save each arr[i] as four values 0 - 3 and implement
Because it is found that interval assignment - > interval inversion can be performed
But interval inversion - > interval assignment will directly become interval assignment
So in update, if col_[rt][c] = 0 needs XOR or 1000 and then down, we assign values in order and then reverse them. That's the order of down.
const int MAX_N = 1000025; int col[MAX_N<<2][4],col_[MAX_N<<2][4],s[MAX_N<<2][4],arr[MAX_N]; void up(int rt,int c) { s[rt][c] = s[rt<<1][c] + s[rt<<1|1][c]; } void down(int rt,int l,int r,int c) { if(col[rt][c]!=-1) { int mid =(l+r)>>1; col[rt<<1][c] = col[rt][c]; col[rt<<1|1][c] = col[rt][c]; col_[rt<<1][c] = 0; col_[rt<<1|1][c] = 0; s[rt<<1][c] = (mid-l+1)*col[rt][c]; s[rt<<1|1][c] = (r-mid)*col[rt][c]; col[rt][c] = -1; } if(col_[rt][c]) { int mid = (l+r)>>1; col_[rt<<1][c] ^= col_[rt][c]; col_[rt<<1|1][c] ^= col_[rt][c]; s[rt<<1][c] = (mid-l+1)-s[rt<<1][c]; s[rt<<1|1][c] = (r-mid)-s[rt<<1|1][c]; col_[rt][c] = 0; } } void update(int rt,int l,int r,int x,int y,int v,int c) { if(x<=l&&r<=y) { col[rt][c] = v; col_[rt][c] = 0; s[rt][c] = (r-l+1)*v; return ; } int mid = (l+r)>>1; down(rt,l,r,c); if(x<=mid) update(rt<<1,l,mid,x,y,v,c); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v,c); up(rt,c); } void update_(int rt,int l,int r,int x,int y,int c) { if(x<=l&&r<=y) { col_[rt][c] ^= 1; s[rt][c] = r-l+1-s[rt][c]; return ; } int mid = (l+r)>>1; down(rt,l,r,c); if(x<=mid) update_(rt<<1,l,mid,x,y,c); if(mid<y) update_(rt<<1|1,mid+1,r,x,y,c); up(rt,c); } void update__(int rt,int l,int r,int x,int c) { if(l==r) { s[rt][c] = 1; return ; } int mid = (l+r)>>1; if(x<=mid) update__(rt<<1,l,mid,x,c); else update__(rt<<1|1,mid+1,r,x,c); up(rt,c); } int query(int rt,int l,int r,int x,int y,int c) { if(x<=l&&r<=y) { return s[rt][c]; } down(rt,l,r,c); int mid = (l+r)>>1,res= 0; if(x<=mid) res+=query(rt<<1,l,mid,x,y,c); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y,c); return res; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t; scanf("%d",&t); while(t--) { memset(s,0,sizeof(s)); memset(col,-1,sizeof(col)); memset(col_,0,sizeof(col_)); char str[10]; int n,Q,opt,x,y,v; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) { scanf("%d",&arr[i]); for(int j = 0;j<4;++j) { if(arr[i]&(1<<j)) { update__(1,1,n,i,j); } } } while(Q--) { scanf("%s",str); if(str[0]=='A') { scanf("%d%d%d",&v,&x,&y); x++,y++; for(int i = 0;i<4;++i) { if(!(v&(1<<i))) { update(1,1,n,x,y,0,i); } } } else if(str[0]=='O') { scanf("%d%d%d",&v,&x,&y); x++,y++; for(int i = 0;i<4;++i) { if(v&(1<<i)) { update(1,1,n,x,y,1,i); } } } else if(str[0]=='X') { scanf("%d%d%d",&v,&x,&y); x++,y++; for(int i = 0;i<4;++i) { if(v&(1<<i)) { update_(1,1,n,x,y,i); } } } else if(str[0]=='S') { scanf("%d%d",&x,&y); x++,y++; int ans = 0; for(int i = 0;i<4;++i) { ans+=(1<<i)*query(1,1,n,x,y,i); } printf("%d\n",ans); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
004.BZOJ 5312
Because this is an interval max, we don't need to build a segment tree based on bits, but a direct hard core segment tree.
This is with or we use a random algorithm to successfully card out the special data how card? That is, if the maxx of your interval equals the min of your interval, then you can modify maxx and min directly, including the lazy array, so that the complexity will not be the worst case.
const int MAX_N = 200025; int maxx[MAX_N<<2],col[MAX_N<<2],minn[MAX_N<<2]; void up(int rt) { maxx[rt] = max(maxx[rt<<1],maxx[rt<<1|1]); minn[rt] = min(minn[rt<<1],minn[rt<<1|1]); } void build(int rt,int l,int r) { col[rt] = -1; if(l==r) { int v; scanf("%d",&v); maxx[rt] = minn[rt] = v; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void down(int rt,int l,int r) { if(col[rt]!=-1) { col[rt<<1] = col[rt<<1|1] = col[rt]; maxx[rt<<1] = maxx[rt<<1|1] = col[rt]; minn[rt<<1] = minn[rt<<1|1] = col[rt]; col[rt] = -1; } } void And(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y&&maxx[rt]==minn[rt]) { maxx[rt] = maxx[rt]&v; minn[rt] = minn[rt]&v; col[rt] = maxx[rt]; return ; } down(rt,l,r); if(x<=mid) And(rt<<1,l,mid,x,y,v); if(mid<y) And(rt<<1|1,mid+1,r,x,y,v); up(rt); } void Or(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y&&maxx[rt]==minn[rt]) { maxx[rt] = maxx[rt]|v; minn[rt] = minn[rt]|v; col[rt] = maxx[rt]; return ; } down(rt,l,r); if(x<=mid) Or(rt<<1,l,mid,x,y,v); if(mid<y) Or(rt<<1|1,mid+1,r,x,y,v); up(rt); } int query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return maxx[rt]; } down(rt,l,r); int maxx1 = 0,maxx2 = 0; if(x<=mid) maxx1 = query(rt<<1,l,mid,x,y); if(mid<y) maxx2 = query(rt<<1|1,mid+1,r,x,y); return max(maxx1,maxx2); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,v; scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&x,&y,&v); And(1,1,n,x,y,v); } else if(opt==2) { scanf("%d%d%d",&x,&y,&v); Or(1,1,n,x,y,v); } else { scanf("%d%d",&x,&y); printf("%d\n",query(1,1,n,x,y)); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
Let's continue to try positive solutions.
const int MAX_N = 200025; int maxx[MAX_N<<2],same[MAX_N<<2]; void up(int rt) { maxx[rt] = max(maxx[rt<<1],maxx[rt<<1|1]); same[rt] = (~(maxx[rt<<1]^maxx[rt<<1|1]))&(same[rt<<1]&same[rt<<1|1]); } void build(int rt,int l,int r) { if(l==r) { int v; scanf("%d",&v); same[rt] = inf; maxx[rt] = v; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void pushnow(int rt,int sm,int mx) { same[rt] |= sm; maxx[rt] = (mx&sm)|(maxx[rt]&(~sm)); } void down(int rt) { pushnow(rt<<1,same[rt],maxx[rt]); pushnow(rt<<1|1,same[rt],maxx[rt]); } void update(int rt,int l,int r,int x,int y,int sm,int v) { if(y<l||x>r) return; if(x<=l&&r<=y) { if(l==r||(sm&same[rt])==sm) { maxx[rt] = (maxx[rt]&(~sm))|(v&sm); return ; } } down(rt); update(rt<<1,l,mid,x,y,sm,v); update(rt<<1|1,mid+1,r,x,y,sm,v); up(rt); } int query(int rt,int l,int r,int x,int y) { if(y<l||x>r) return 0; if(x<=l&&r<=y) { return maxx[rt]; } down(rt); int maxx1 = 0,maxx2 = 0; maxx1 = query(rt<<1,l,mid,x,y); maxx2 = query(rt<<1|1,mid+1,r,x,y); return max(maxx1,maxx2); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,v; scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d",&x,&y,&v); update(1,1,n,x,y,inf^v,0); } else if(opt==2) { scanf("%d%d%d",&x,&y,&v); update(1,1,n,x,y,v,v); } else { scanf("%d%d",&x,&y); printf("%d\n",query(1,1,n,x,y)); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
005 Hdu 3911
The meaning of this paper is to give you a sequence of 01 containing N-N n elements with m operations of 0 and the longest number of outputs between x and y.
Operator 1 reverses all numbers in the x y interval
This question was written in June last year. It's just a sentence that I can't understand. Today, I'll recapitulate this question.
Similar intervals can be obtained by a property (left, right, middle). We use segment trees to do the problem.
In this problem, we define two structured bodies arr1 and arr2 arr1 as a tree of consecutive 1 in the original sequence.
Ar2 is a tree with consecutive zeros in the original sequence.
Now that you invert an interval by one operation, just change the 1 tree and the 0 tree directly.
int Max(int a,int b) { if(a>b) return a; return b; } int Min(int a,int b) { if(a<b) return a; return b; } void Swap(int &x,int &y) { int t = x; x = y; y = t; } const int MAX_N = 100025; struct node { int down,ls0,rs0,ls1,rs1,ms0,ms1; }arr[MAX_N<<2]; void up(int rt,int l,int r) { arr[rt].ls1 = arr[rt<<1].ls1; arr[rt].rs1 = arr[rt<<1|1].rs1; if(arr[rt].ls1==mid-l+1) arr[rt].ls1+=arr[rt<<1|1].ls1; if(arr[rt].rs1==r-mid) arr[rt].rs1+=arr[rt<<1].rs1; arr[rt].ms1 = Max(arr[rt<<1].ms1,arr[rt<<1|1].ms1); arr[rt].ms1 = Max(arr[rt].ms1,Max(Max(arr[rt].ls1,arr[rt].rs1),arr[rt<<1].rs1+arr[rt<<1|1].ls1)); arr[rt].ls0 = arr[rt<<1].ls0; arr[rt].rs0 = arr[rt<<1|1].rs0; if(arr[rt].ls0==mid-l+1) arr[rt].ls0+=arr[rt<<1|1].ls0; if(arr[rt].rs0==r-mid) arr[rt].rs0+=arr[rt<<1].rs0; arr[rt].ms0 = Max(arr[rt<<1].ms0,arr[rt<<1|1].ms0); arr[rt].ms0 = Max(arr[rt].ms0,Max(Max(arr[rt].ls0,arr[rt].rs0),arr[rt<<1].rs0+arr[rt<<1|1].ls0)); } void SWAP(int rt) { Swap(arr[rt].ls1,arr[rt].ls0); Swap(arr[rt].rs1,arr[rt].rs0); Swap(arr[rt].ms1,arr[rt].ms0); } void down(int rt,int l,int r) { if(arr[rt].down) { arr[rt].down^=1; arr[rt<<1].down^=1; arr[rt<<1|1].down^=1; SWAP(rt<<1),SWAP(rt<<1|1); } } void build(int rt,int l,int r) { arr[rt].down = arr[rt].ls0 = arr[rt].ls1=arr[rt].ms0=arr[rt].ms1=arr[rt].ms0 =arr[rt].rs0=arr[rt].rs1= 0; if(l==r) { int v; scanf("%d",&v); if(v) { arr[rt].ls1 = arr[rt].rs1 = arr[rt].ms1 = 1; } else { arr[rt].ls0 = arr[rt].rs0 = arr[rt].ms0 = 1; } return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt,l,r); } void update(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { arr[rt].down^=1; SWAP(rt); return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y); if(mid<y) update(rt<<1|1,mid+1,r,x,y); up(rt,l,r); } node query(int rt,int l ,int r,int x,int y) { if(x<=l&&r<=y) { return arr[rt]; } down(rt,l,r); if(x<=mid&&y>mid) { node tmp1 = query(rt<<1,l,mid,x,y); node tmp2 = query(rt<<1|1,mid+1,r,x,y); node ans; ans.ls1 = tmp1.ls1,ans.ls0 = tmp1.ls0; ans.rs0 = tmp2.rs0,ans.rs1 = tmp2.rs1; if(ans.ls1 == mid-l+1) ans.ls1+=tmp2.ls1; if(ans.ls0==mid-l+1) ans.ls0+=tmp2.ls0; if(ans.rs0==r-mid) ans.rs0+=tmp1.rs0; if(ans.rs1==r-mid) ans.rs1 += tmp1.rs1; ans.ms1 = Max(Max(Max(tmp1.ms1,tmp2.ms1),Max(ans.ls1,ans.rs1)),tmp1.rs1+tmp2.ls1); return ans; } else if(x<=mid) { return query(rt<<1,l,mid,x,y); } else if(x>mid) { return query(rt<<1|1,mid+1,r,x,y); } } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y; while(scanf("%d",&n)==1) { build(1,1,n); scanf("%d",&Q); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==0) { printf("%d\n",query(1,1,n,x,y).ms1); } else { update(1,1,n,x,y); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
006 HDU5634
There are three operations in an interval. One operation turns all the numbers in the interval into their Euler functions.
2 Operations replace all numbers in an interval with a value
3 Operations to Find Interval Sums
Because the Euler function of a number is unchanged after many times. We only need to use a sample array as a time-saving method to save time and complexity. It should be O(nlogn).
Then forgetting l==r return at change results in a constant re
phi[1] is not initialized to 1, resulting in a constant tle
const int MAX_N = 10000025; bool vis[MAX_N]; int n; ll cnt,prime[MAX_N],phi[MAX_N]; void sieve(int n) { phi[1] = 1; memset(vis,false,sizeof(vis));cnt = 0; for(int i = 2;i<n;++i) { if(!vis[i]) { prime[cnt++] = i; phi[i] = i - 1; } for(int j = 0;j<cnt&&i*prime[j]<n;++j) { int k = i *prime[j]; vis[k] = true; if(i%prime[j]==0) { phi[k] = phi[i] * prime[j]; break; } phi[k] = phi[i] * (prime[j]-1); } } } ll same[300025*4],s[300025*4]; int Max(int a,int b){if(a>b) return a;return b;} int Min(int a,int b){if(a<b) return a;return b;} void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; same[rt] = (same[rt<<1]==same[rt<<1|1])?same[rt<<1]:0; } void build(int rt,int l,int r) { s[rt] = 0,same[rt] = 0; if(l==r) { scanf("%lld",&s[rt]); same[rt] = s[rt]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void down(int rt,int l,int r) { if(same[rt]) { s[rt<<1] = 1ll*(mid-l+1)*same[rt]; s[rt<<1|1] = 1ll*(r-mid)*same[rt]; same[rt<<1] = same[rt]; same[rt<<1|1] = same[rt]; same[rt] = 0; } } void update(int rt,int l,int r,int x,int y,ll v) { if(x<=l&&r<=y) { same[rt] = v; s[rt] = 1ll*(r-l+1)*v; return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y,v); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v); up(rt); } void change(int rt,int l,int r,int x,int y) { if(x>r||y<l) return; if(x<=l&&r<=y&&same[rt]) { same[rt] = phi[same[rt]]; s[rt] = 1ll*(r-l+1)*same[rt]; return ; } if(l==r) return; down(rt,l,r); if(x<=mid) change(rt<<1,l,mid,x,y); if(mid<y) change(rt<<1|1,mid+1,r,x,y); up(rt); } ll query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } down(rt,l,r); ll res = 0; if(x<=mid) res+=query(rt<<1,l,mid,x,y); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y); up(rt); return res; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t,opt,x,y,z; sieve(MAX_N); scanf("%d",&t); while(t--) { int Q; scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { change(1,1,n,x,y); } else if(opt==2) { scanf("%d",&z); update(1,1,n,x,y,1ll*z); } else if(opt==3) { printf("%lld\n",query(1,1,n,x,y)); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
In fact, I have written blogs on this topic before.
Unfortunately, at that time, young people did not understand how to learn the algorithm in the first month of learning XX line tree, but also with a sentence to solve the problem.
How do we do this? We need to record the number of prefixes with the longest consecutive 0 ls.
The Number of Suffixes of the Longest Continuous 0 rs
Number ms of the longest continuous 0 of intervals
Then the interval substitution is the same as the general interval substitution.
Whether the ms of the left son is larger than v when looking for it first
If not satisfied with finding left son rs + right son ls is greater than v
If you are not satisfied, find out if the right son ms is larger than v
Then when you find it, you need to replace the interval with 1.
2 The operation is to replace the bare interval with zero.
The code is as follows
const int MAX_N = 50025; int Max(int a,int b) { if(a>b) return a; return b; } int Min(int a,int b) { if(a<b) return a; return b; } struct node { int ls,rs,ms,down; }arr[MAX_N<<2]; void up(int rt,int l,int r) { arr[rt].ls = arr[rt<<1].ls; arr[rt].rs = arr[rt<<1|1].rs; if(arr[rt].ls==mid-l+1) arr[rt].ls += arr[rt<<1|1].ls; if(arr[rt].rs==r-mid) arr[rt].rs += arr[rt<<1].rs; arr[rt].ms = Max(arr[rt<<1].ms,arr[rt<<1|1].ms); arr[rt].ms = Max(arr[rt].ms,Max(arr[rt<<1].rs+arr[rt<<1|1].ls,Max(arr[rt].ls,arr[rt].rs))); } void down(int rt,int l,int r) { if(arr[rt].down!=-1) { arr[rt<<1].down = arr[rt].down; arr[rt<<1|1].down = arr[rt].down; arr[rt<<1].rs = arr[rt<<1].ms = arr[rt<<1].ls = (mid- l+1)*(1-arr[rt].down); arr[rt<<1|1].ls = arr[rt<<1|1].rs = arr[rt<<1|1].ms = (r-mid)*(1-arr[rt].down); arr[rt].down = -1; } } void build(int rt,int l,int r) { arr[rt].down = -1;arr[rt].ls = 0,arr[rt].rs = 0,arr[rt].ms = 0; if(l==r) { arr[rt].ls = arr[rt].rs = arr[rt].ms = 1; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt,l,r); } void update(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y) { arr[rt].down = v; arr[rt].ls = arr[rt].rs = arr[rt].ms = (1-v)*(r-l+1); return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y,v); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v); up(rt,l,r); } int query(int rt,int l,int r,int x,int y,int v) { if(l==r) { return l; } down(rt,l,r); if(arr[rt<<1].ms>=v) return query(rt<<1,l,mid,x,y,v); else if(arr[rt<<1].rs+arr[rt<<1|1].ls>=v) return mid - arr[rt<<1].rs + 1; else if(arr[rt<<1|1].ms>=v) return query(rt<<1|1,mid+1,r,x,y,v); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y; scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d%d",&opt,&x); if(opt==1) { if(arr[1].ms<x) { printf("0\n"); } else { int ans = query(1,1,n,1,n,x); printf("%d\n",ans); update(1,1,n,ans,ans+x-1,1); } } else { scanf("%d",&y); update(1,1,n,x,x+y-1,0); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
008 BZOJ 5028
The smallest water that can be poured out of this bottle is actually not
ax + by + cz +... Is the Minimum Integer Solution of km
From Peishu Theorem, we can see that this solution is their interval gcd.
Then the answer is converted to interval gcd and interval update
Segment trees must be timed out if they are to be maintained
So what do we do?
We know that gcd(x,y) = gcd(x,y-x)
gcd(x,y,z) = gcd(x,gcd(y,z))
Then the interval gcd of X - > y can be transformed into the gcd of arr[x] and x+1 and Y on the differential segment tree
The previous arr[x] is maintained with a tree array
The line tree of the following x+1 and y gcd can be maintained directly because gcd satisfies interval transitivity
Maybe the code is a bit ugly. Actually, abs is only required, but abs is prone to problems in the long run, so it writes a special judgment.
const int MAX_N = 200005; ll arr[MAX_N],s[MAX_N<<2],C[MAX_N<<1]; void add(int x,int v) { for(;x<MAX_N;x+=x&(-x)) C[x]+=v; } int getsum(int x) { int res= 0; for(;x;x-=x&(-x)) res+=C[x]; return res; } void up(int rt) { s[rt] = gcd(s[rt<<1],s[rt<<1|1]); } void build(int rt,int l,int r) { if(l==r) { if(l==1) s[rt] = arr[1]; else s[rt] = arr[l] - arr[l-1]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v) { if(l==r) { s[rt]+=v; return; } if(x<=mid) update(rt<<1,l,mid,x,v); else update(rt<<1|1,mid+1,r,x,v); up(rt); } ll query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } if(x>mid) return query(rt<<1|1,mid+1,r,x,y); if(y<=mid) return query(rt<<1,l,mid,x,y); return gcd(query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y)); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,v; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) scanf("%lld",&arr[i]); build(1,1,n); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { if(x==y) { ll ans = arr[x]+getsum(x); if(ans<0) ans*=-1; printf("%lld\n",ans); } else { ll ans = gcd(arr[x]+getsum(x),query(1,1,n,x+1,y)); if(ans<0) ans*=-1; printf("%lld\n",ans); } } else { scanf("%d",&v); add(x,v); add(y+1,-v); update(1,1,n,x,v); update(1,1,n,y+1,-v); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
009 CF914D
The meaning of the question gives you n numbers and two operations.
2 Single point modification of operation
1 operation x y v asks you if the number gcd in the X and Y intervals is v when the number of modifications is less than or equal to 1
Let's first maintain an interval gcd
Then go to the very saucy query to query about the idea of pruning. I found that if an interval% v==0, then I don't have to look it up.
Otherwise to the root if gcd%v!=0 then I need to change it once.
This is the code written in this way.
const int MAX_N = 500025; ll s[MAX_N<<2]; int tmp; void up(int rt) { s[rt] = gcd(s[rt<<1],s[rt<<1|1]); } void build(int rt,int l,int r) { if(l==r) { scanf("%lld",&s[rt]); return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v) { if(l==r) { s[rt] = v; return ; } if(x<=mid) update(rt<<1,l,mid,x,v); else update(rt<<1|1,mid+1,r,x,v); up(rt); } void ask(int rt,int l,int r,int x,int y,int v) { if(tmp>=2) return; if(l==r) { if(s[rt]%v!=0) tmp++; return; } if(x<=l&&r<=y) { if(s[rt]%v!=0) { ask(rt<<1,l,mid,x,y,v); ask(rt<<1|1,mid+1,r,x,y,v); } return ; } if(x>mid) return ask(rt<<1|1,mid+1,r,x,y,v); if(y<=mid) return ask(rt<<1,l,mid,x,y,v); ask(rt<<1,l,mid,x,y,v),ask(rt<<1|1,mid+1,r,x,y,v); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,v; scanf("%d",&n); build(1,1,n); scanf("%d",&Q); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { scanf("%d",&v); tmp = 0; ask(1,1,n,x,y,v); if(tmp>=2) printf("NO\n"); else printf("YES\n"); } else { update(1,1,n,x,y); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
010 CF877E
Give you a tree
get operation to find the number of lights on in the tree subtree
The pow operation reverses the light-on state in this subtree
We just need to build a segment tree with dfs order
Then sum the intervals of get operation
For the pow operation interval, take the inverse
const int MAX_N = 200025; int p[MAX_N],eid,s[MAX_N<<2],col[MAX_N<<2],low[MAX_N],high[MAX_N],dep,arr[MAX_N],Rank[MAX_N]; struct { int v,next; }e[MAX_N<<1]; void init() { memset(p,-1,sizeof(p)); eid = 0; } void add(int u,int v) { e[eid].v = v; e[eid].next = p[u]; p[u] = eid++; } void dfs(int u,int fa) { low[u] = ++dep; Rank[dep] = u; for(int i = p[u];~i;i=e[i].next) if(e[i].v!=fa) dfs(e[i].v,u); high[u] = dep; } void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; } void build(int rt,int l,int r) { col[rt] = 0; if(l==r) { s[rt] = arr[Rank[l]]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void down(int rt,int l,int r) { if(col[rt]) { col[rt<<1] ^= 1; col[rt<<1|1] ^= 1; s[rt<<1] = mid-l+1-s[rt<<1]; s[rt<<1|1] = r-mid - s[rt<<1|1]; col[rt] = 0; } } void update(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { col[rt] ^= 1; s[rt] = r-l+1-s[rt]; return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y); if(mid<y) update(rt<<1|1,mid+1,r,x,y); up(rt); } int query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } int res = 0; down(rt,l,r); if(x<=mid) res+=query(rt<<1,l,mid,x,y); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y); return res; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int Q,n,a,x; char str[5]; init(); scanf("%d",&n); for(int i = 2;i<=n;++i) { scanf("%d",&a); add(a,i),add(i,a); } for(int i= 1;i<=n;++i) scanf("%d",&arr[i]); dfs(1,0); build(1,1,n); scanf("%d",&Q); while(Q--) { scanf("%s",str); if(str[0]=='g') { scanf("%d",&x); printf("%d\n",query(1,1,n,low[x],high[x])); } else { scanf("%d",&x); update(1,1,n,low[x],high[x]); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
011 BZOJ 3211
Interval Sum and Point Modification of Topic Meaning Interval
In fact, as long as the current Maxx <= 1 does not need to continue the prescription.
At first, the code was ugly. T should be shared equally. No T
Later, it was adjusted.
const int MAX_N = 100025; int maxx[MAX_N<<2]; ll s[MAX_N<<2]; void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; maxx[rt] = max(maxx[rt<<1],maxx[rt<<1|1]); } void build(int rt,int l,int r) { if(l==r) { scanf("%d",&maxx[rt]); s[rt] = maxx[rt]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } ll query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } ll res = 0; if(x<=mid) res+= query(rt<<1,l,mid,x,y); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y); return res; } void update(int rt,int l,int r,int x,int y) { if(maxx[rt]<=1) return; if(l==r) { s[rt] = sqrt(s[rt]); maxx[rt] = s[rt]; return; } if(y<=mid) update(rt<<1,l,mid,x,y); else if(x>mid) update(rt<<1|1,mid+1,r,x,y); else { update(rt<<1,l,mid,x,y); update(rt<<1|1,mid+1,r,x,y); } up(rt); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y; scanf("%d",&n); build(1,1,n); scanf("%d",&Q); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { printf("%lld\n",query(1,1,n,x,y)); } else { update(1,1,n,x,y); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
012 HDOJ5828
The meaning of the question is to give you n numbers. There are three operations. One is to add v to the number of l - r.
2 l r gives l - r the number of all prescriptions
3 l r to find the sum of l - r
Beginning with the simplest case, if there is no 1 operation, only interval square and interval sum can be referred to in this blog.
BZOJ 3211
The problem is that there are additions.
We need to know that the Maxx - min value of this interval will be smaller and smaller when the prescription has a property more times.
That's the formula.
x+d  −  y+d  <=  x  −  y
\sqrt{x+d}\,\,-\,\,\sqrt{y+d}\,\,<=\,\,\sqrt{x}\,\,-\,\,\sqrt{y}
x+d​−y+d​<=x​−y​
So we know that if the interval Maxx <== 1 is the square, then we don't need to do the square operation.
If this interval Maxx - Minn > 1, we need to do the prescription operation
Why do we need special judgement when maxx-min equals 1?
Because we found that, for example, 34, their original maxx was 4 min and 3.
maxx is 2 min and 1 min after crossover
You will find that 4 - > 2, 3 - > 1 is not an interval addition process, so this can be optimized by interval addition.
Another case is that 23 Maxx is 3 min and 2
After crossover, maxx = minn = 1
Isn't that the process of interval replacement?
It is the operation of optimizing time by utilizing this property.
So operation 2 becomes no operation.
Do you want interval addition?
Do you want to change the interval?
Do you want violent revision?
Then at first, s didn't notice that it was all two long WA rounds.
const int MAX_N = 100025; int maxx[MAX_N<<2],minn[MAX_N<<2],col[MAX_N<<2],seto[MAX_N<<2]; ll s[MAX_N<<2]; int Max(int a,int b){if(a>b) return a;return b;} int Min(int a,int b){if(a<b) return a;return b;} void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]); minn[rt] = Min(minn[rt<<1],minn[rt<<1|1]); } void down(int rt,int l,int r) { if(seto[rt]!=-1) { s[rt<<1] = 1ll*(mid-l+1)*seto[rt]; s[rt<<1|1] = 1ll*(r-mid)*seto[rt]; maxx[rt<<1] = maxx[rt<<1|1] = seto[rt]; minn[rt<<1] = minn[rt<<1|1] = seto[rt]; seto[rt<<1] = seto[rt<<1|1] = seto[rt]; col[rt<<1] = col[rt<<1|1] = 0; seto[rt]=-1; } if(col[rt]) { s[rt<<1] += 1ll*(mid-l+1)*col[rt]; s[rt<<1|1] += 1ll*(r-mid)*col[rt]; col[rt<<1] += col[rt]; col[rt<<1|1] += col[rt]; maxx[rt<<1] += col[rt]; maxx[rt<<1|1] += col[rt]; minn[rt<<1] += col[rt]; minn[rt<<1|1] += col[rt]; col[rt] = 0; } } void build(int rt,int l,int r) { seto[rt] = -1;col[rt] = 0;maxx[rt] = minn[rt] = s[rt] = 0; if(l==r) { scanf("%lld",&s[rt]); maxx[rt] = minn[rt] = s[rt]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void change(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y) { s[rt] += 1ll*v*(r-l+1); col[rt] += v; maxx[rt] += v; minn[rt] += v; return ; } down(rt,l,r); if(x<=mid) change(rt<<1,l,mid,x,y,v); if(mid<y) change(rt<<1|1,mid+1,r,x,y,v); up(rt); } void update(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { if(maxx[rt]<=1) return; if(l==r) { s[rt] = floor(sqrt(s[rt])); maxx[rt] = minn[rt] = s[rt]; return ; } if(maxx[rt] == minn[rt]) { int tmp = maxx[rt]; maxx[rt] = minn[rt] = floor(sqrt(tmp)); seto[rt] = maxx[rt];col[rt] = 0; s[rt] = 1ll*(r-l+1) * maxx[rt]; return; } else if(maxx[rt]-minn[rt]==1) { int ta = maxx[rt],tb = minn[rt]; maxx[rt] = floor(sqrt(maxx[rt])); minn[rt] = floor(sqrt(minn[rt])); if(ta-maxx[rt]==tb-minn[rt]) { col[rt] += maxx[rt] - ta; s[rt] += 1ll*(maxx[rt]-ta)*(r-l+1); } else { col[rt] = 0;seto[rt] = maxx[rt]; s[rt] = 1ll*(r-l+1)*maxx[rt]; } return; } down(rt,l,r); update(rt<<1,l,mid,x,y); update(rt<<1|1,mid+1,r,x,y); up(rt); return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y); if(mid<y) update(rt<<1|1,mid+1,r,x,y); up(rt); } ll query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } ll res =0; down(rt,l,r); if(x<=mid) res+= query(rt<<1,l,mid,x,y); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y); return res; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t,n,Q,opt,x,y,v; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { scanf("%d",&v); change(1,1,n,x,y,v); } else if(opt==2) { update(1,1,n,x,y); } else { printf("%lld\n",query(1,1,n,x,y)); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
013 cf 160E
The title gives you the starting coordinates, terminating coordinates and starting time of n buses.
Q Individual Starting Coordinate Termination Coordinate and Starting Time
As long as the starting coordinate of the person is satisfied after the starting coordinate of the bus and the terminating coordinate is before the terminating coordinate of the bus.
And the time is before the start of the bus, people can get on the bus.
Ask each of you which bus has the earliest start-up time and output-1 if you can't.
In this way, we first put all the coordinates of people and buses together and sort them according to the starting coordinates of the first keyword.
The second keyword id (which guarantees that the car must be in front of the person at the same time)
This way, when you ask everyone, you can make sure that the bus you've dealt with before starts in front of that person.
And then what do we do?
Because it takes the least time to set up a segment tree with time as nodes, each node has the largest termination coordinates at that time.
So everyone just asks him if the termination coordinate is greater than his minimum time after the time.
You can find it by querying the segment tree.
Then the update time is to insert the termination coordinates and bus number to that time.
const int MAX_N = 200025; int b[MAX_N<<1],ans[MAX_N],tm[MAX_N],maxx[MAX_N<<2],id[MAX_N<<2]; int Max(int a,int b){if(a>b) return a;return b;} struct node { int l,r,tm,id; bool operator<(const node other) const { if(l==other.l) return id < other.id; return l < other.l; } }arr[MAX_N<<1]; void up(int rt) { maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]); } void build(int rt,int l,int r) { maxx[rt] = 0; if(l==r) { maxx[rt] = -inf; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v,int ID) { if(l==r) { maxx[rt] = v; id[rt] = ID; return ; } if(x<=mid) update(rt<<1,l,mid,x,v,ID); else update(rt<<1|1,mid+1,r,x,v,ID); up(rt); } int query(int rt,int l,int r,int x,int y,int v) { if(maxx[rt]<v) { return -1; } if(l==r) { return id[rt]; } int ans = -1; if(maxx[rt<<1]>=v&&x<=mid) { ans = query(rt<<1,l,mid,x,y,v); if(ans!=-1) return ans; } return query(rt<<1|1,mid+1,r,x,y,v); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,cnt = 0,cnt_ = 0; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) { scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].tm); arr[i].id = i;tm[++cnt_] = arr[i].tm; b[++cnt] = arr[i].l,b[++cnt] = arr[i].r; } for(int i = n+1;i<=n+Q;++i) { scanf("%d%d%d",&arr[i].l,&arr[i].r,&arr[i].tm); arr[i].id = i;tm[++cnt_] = arr[i].tm; b[++cnt] = arr[i].l,b[++cnt] = arr[i].r; } sort(b+1,b+1+cnt); sort(tm+1,tm+1+cnt_); int sz = unique(b+1,b+1+cnt)-b-1; int sz_ = unique(tm+1,tm+1+cnt_) - tm - 1; build(1,1,n+Q); for(int i = 1;i<=n+Q;i++) { arr[i].tm = lower_bound(tm+1,tm+1+sz_,arr[i].tm) - tm; arr[i].l = lower_bound(b+1,b+1+sz,arr[i].l) - b; arr[i].r = lower_bound(b+1,b+1+sz,arr[i].r) - b; } sort(arr+1,arr+1+n+Q); for(int i = 1;i<=n+Q;i++) { if(arr[i].id <=n) { update(1,1,n+Q,arr[i].tm,arr[i].r,arr[i].id); } else { //dbg3(i,arr[i].id,query(1,1,n+Q,arr[i].tm,n+Q,arr[i].r)); ans[arr[i].id] = query(1,1,n+Q,arr[i].tm,n+Q,arr[i].r); } } for(int i = n+1;i<=n+Q;++i) printf("%d ",ans[i]); //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
014 CF 19D
The title is expressed.
Give you a Cartesian coordinate system, which now supports three operations.
The first operation is to add a point (x,y).
The second operation is to delete a point (x,y).
The third operation is to query the point with the smallest abscissa in the top right corner of the point (x,y). If there are more than one point, choose the one with the smallest ordinate.
set comes to mind in this question.
Then how to find the strict upper right corner? Think of the segment tree to find the leftmost coordinate of the right interval where maxx is greater than y+1
We use abscissa to store the maximum value of ordinate in abscissa with the help of rbegin of set.
The 1500ms code run should have some RE-optimization, but A is a good array with two small REs
const int MAX_N = 200025; int x[MAX_N],y[MAX_N],b[MAX_N<<1],maxx[MAX_N<<3],ans[MAX_N][2]; char str[MAX_N][10]; set<int > st[MAX_N<<1]; map<int ,int > mp; int Max(int a,int b){if(a>b) return a;return b;} void up(int rt) { maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]); } void build(int rt,int l,int r) { maxx[rt] = -1; if(l==r) { return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v) { if(l==r) { if(v==1) { maxx[rt] = *st[x].rbegin(); } else { if(st[x].empty()) maxx[rt] = -1; else maxx[rt] = *st[x].rbegin(); } return ; } if(x<=mid) update(rt<<1,l,mid,x,v); else update(rt<<1|1,mid+1,r,x,v); up(rt); } int query(int rt,int l,int r,int x,int y,int v) { if(maxx[rt]<v) return -1; if(l==r) { return l; } int ans = -1; if(x<=mid) { ans = query(rt<<1,l,mid,x,y,v); if(ans!=-1) return ans; } return query(rt<<1|1,mid+1,r,x,y,v); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,cnt = 0,N = 400000,CNT=1; scanf("%d",&n); mp[-1] = -1; for(int i = 1;i<=n;++i) { scanf("%s",str[i]); scanf("%d%d",&x[i],&y[i]); b[++cnt] = x[i];b[++cnt] = y[i]; } sort(b+1,b+1+cnt); int sz = unique(b+1,b+1+cnt)-b-1; for(int i = 1;i<=n;++i) { int tmp; tmp = lower_bound(b+1,b+1+sz,x[i])-b; mp[tmp] = x[i]; x[i] = tmp; tmp = lower_bound(b+1,b+1+sz,y[i])-b; mp[tmp] = y[i]; y[i] = tmp; } build(1,1,N); for(int i = 1;i<=n;++i) { if(str[i][0]=='a') { st[x[i]].insert(y[i]); update(1,1,N,x[i],1); } else if(str[i][0]=='f') { int tmp = query(1,1,N,x[i]+1,N,y[i]+1); ans[CNT][0] = mp[tmp]; if(ans[CNT][0]!=-1) { set<int>::iterator xb = st[tmp].upper_bound(y[i]); ans[CNT][1] = mp[*xb]; } CNT++; } else if(str[i][0]=='r') { st[x[i]].erase(y[i]); update(1,1,N,x[i],-1); } } for(int i = 1;i<CNT;++i) { printf("%d",ans[i][0]); if(ans[i][0]==-1) printf("\n"); else { printf(" %d\n",ans[i][1]); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
015 BZOJ 5334
I give you n operations 1 y operation is multiplying the original value by one y
The 2y operation divides the original value by the value of the YTH operation
Output the value after each operation
Because it's a product.
So you build a segment tree according to the number of modifications.
So your first operation is to change the single point of the first operation to y.
The second operation is to change the single point of the y-th operation to 1.
Then output s[1] each time.
const int MAX_N = 100025; int mod; ll s[MAX_N<<2]; void up(int rt) { s[rt] = s[rt<<1] * s[rt<<1|1] %mod; } void build(int rt,int l,int r) { s[rt] = 1; if(l==r) { return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v) { if(l==r) { s[rt] = v%mod; return ; } if(x<=mid) update(rt<<1,l,mid,x,v); else update(rt<<1|1,mid+1,r,x,v); up(rt); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t,n,x,y; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&mod); build(1,1,n); for(int i = 1;i<=n;++i) { scanf("%d%d",&x,&y); if(x==1) { update(1,1,n,i,y); printf("%lld\n",s[1]); } else { update(1,1,n,y,1); printf("%lld\n",s[1]); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
016 P1438
To add an interval with a sequence of equidistances whose prime minister is k tolerance and d tolerance
Seeking single point value
Firstly, we construct a difference line segment tree. If we add a sequence of equidistances from l to r in an interval with the prime minister k tolerance d.
Is it equivalent to adding k to the difference array of l?
Add d to the array from l+1 to r
r+1 plus - (k+(r-l+1-1)*d)
Then, using the prefix of the difference array and the value exactly equal to this point, we can directly query and add the value of the original array.
This method is good although it is good, but I personally feel that maintaining a single point value is still a good interval and a little overhanging (maybe I don't understand enough).
Of course, the length of a single O(r+l) can be calculated by using the properties of difference arrays.
const int MAX_N = 100025; int s[MAX_N<<2],arr[MAX_N],col[MAX_N<<2]; void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; } void down(int rt,int l,int r) { if(col[rt]) { col[rt<<1] += col[rt]; col[rt<<1|1] += col[rt]; s[rt<<1] += (mid-l+1)*col[rt]; s[rt<<1|1] += (r-mid)*col[rt]; col[rt] = 0; } } void update(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y) { col[rt] += v; s[rt] += (r-l+1)*v; return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y,v); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v); up(rt); } int query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } int res = 0; down(rt,l,r); if(x<=mid) res+=query(rt<<1,l,mid,x,y); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y); return res; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,k,d; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) scanf("%d",&arr[i]); while(Q--) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d%d",&x,&y,&k,&d); update(1,1,n,x,x,k); if(y>x) update(1,1,n,x+1,y,d); update(1,1,n,y+1,y+1,-((y-x)*d+k)); } else { scanf("%d",&x); printf("%d\n",arr[x]+query(1,1,n,1,x)); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
Let's try the hard core segment tree version.
The reason for the hard core segment tree is that the sequence of equidistances actually satisfies the transitivity in the interval (of course, the sequence of equidistances is not satisfied).
Because this problem solves the single point value, we can pass it down without up directly.
Explain in the code
const int MAX_N = 100025; int sta[MAX_N<<2],d[MAX_N<<2],arr[MAX_N]; void down(int rt,int l,int r) { if(sta[rt]||d[rt]) { d[rt<<1] += d[rt]; d[rt<<1|1] += d[rt];//Tolerances are of course transferable. sta[rt<<1] += sta[rt];//Start the subscription on the left to add father sta[rt<<1|1] += (mid-l+1)*d[rt]+sta[rt];//Begin to subscribe on the right to add the tolerance of father and left son sta[rt] = d[rt] = 0; } } void update(int rt,int l,int r,int x,int y,int k,int D) { if(x<=l&&r<=y) { sta[rt]+=k+(l-x)*D;//How many D does the starting coordinate add to the starting k and how many D does it differ from? d[rt]+=D; return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y,k,D); if(mid<y) update(rt<<1|1,mid+1,r,x,y,k,D); } int query(int rt,int l,int r,int x) { if(l==r) { return arr[l] + sta[rt]; } down(rt,l,r); if(x<=mid) return query(rt<<1,l,mid,x); else return query(rt<<1|1,mid+1,r,x); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,K,D; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) scanf("%d",&arr[i]); while(Q--) { scanf("%d",&opt); if(opt==1) { scanf("%d%d%d%d",&x,&y,&K,&D); update(1,1,n,x,y,K,D); } else { scanf("%d",&x); printf("%d\n",query(1,1,n,x)); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
017 Sorry, I can't answer this question.
input
13 5 8
8 4 10 4
4 3 4 4
10 2 12 2
8 2 8 4
2 4 6 4
10 3 10 4
12 3 12 4
2 2 4 2
output
3
Remarks
[Data Scope]
For 30% of the data, p < 1000.
For 70% of the data, p < 30000.
For 100% data, p < 400000; m,n < 1000000.
In this way, we first construct a line segment tree with the longest continuous length of 0 in each abscissa.
To the left of the rectangle, we add
On the right side of the rectangle, we delete it.
Then we use double pointer sweep energy from left to right to form a minimum square edge length of min(r-l+1,ms[1]).
If MS [1] < R-L + 1, then we need to move l to the right, so we can run with two pointers.
const int MAX_N = 1000025; int ms[MAX_N<<2],ls[MAX_N<<2],rs[MAX_N<<2],col[MAX_N<<2]; int Max(int a,int b){if(a>b) return a;return b;} vector<int > add[MAX_N/2],del[MAX_N/2]; int x[2][MAX_N/2],y[2][MAX_N/2]; void up(int rt,int l,int r) { if(col[rt]) {ms[rt] = ls[rt] = rs[rt] = 0;return ;} if(l==r) {ms[rt] = ls[rt] = rs[rt] = 1;return ;} ls[rt] = ls[rt<<1] + (ls[rt<<1]==(mid-l+1)?ls[rt<<1|1]:0); rs[rt] = rs[rt<<1|1] + (rs[rt<<1|1] == (r-mid)?rs[rt<<1]:0); ms[rt] = Max(rs[rt<<1]+ls[rt<<1|1],Max(ms[rt<<1],ms[rt<<1|1])); } void build(int rt,int l,int r) { ms[rt] = ls[rt] = rs[rt] = r-l+1,col[rt] = 0; if(l==r) { return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); } void update(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y) { col[rt]+=v; up(rt,l,r); return ; } if(x<=rt) update(rt<<1,l,mid,x,y,v); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v); up(rt,l,r); } int query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return ms[rt]; } int maxx1 = 0,maxx2 = 0; if(x<=mid) maxx1 = query(rt<<1,l,mid,x,y); if(mid<y) maxx2 = query(rt<<1|1,mid+1,r,x,y); return Max(maxx1,maxx2); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,m,p; scanf("%d%d%d",&n,&m,&p); for(int i = 1;i<=p;++i) { scanf("%d%d%d%d",&x[0][i],&y[0][i],&x[1][i],&y[1][i]); add[x[0][i]].push_back(i); del[x[1][i]].push_back(i); } build(1,1,m); int l = 1,r = 1,ans = 0; while(r<=n) { for(int it = 0;it<add[r].size();it++) update(1,1,m,y[0][add[r][it]],y[1][add[r][it]],1); ans = max(ans,min(ms[1],r-l+1)); while(ms[1]<r-l+1) { for(int it = 0;it<del[l].size();++it) update(1,1,m,y[0][del[l][it]],y[1][del[l][it]],-1); l++; } r++; } printf("%d\n",ans); //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
018 CF438D
Item 1 Summation of Operational Intervals
2 Operating Interval Modeling
3 Single point modification of operation
The subject itself is very metaphysical
With a single update, it can be done as long as Maxx [rt] < V (modular number) return
According to the theorem, as long as the size of each module is reduced by at least half, the maximum log2 times.
So the time complexity is O(nloglogn)
But I've written an interval Maxx [rt]== Minn [rt] for interval coverage, and I've been writing errors all the time. I don't know why.
Let's be honest and send a single update.
const int MAX_N = 100025; ll s[MAX_N<<2]; int maxx[MAX_N<<2],minn[MAX_N<<2]; int Max(int a,int b){if(a>b) return a;return b;} int Min(int a,int b){if(a<b) return a;return b;} void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]); minn[rt] = Min(minn[rt<<1],minn[rt<<1|1]); } void build(int rt,int l,int r) { maxx[rt] = minn[rt] = s[rt] = 0; if(l==r) { scanf("%lld",&s[rt]); maxx[rt] = minn[rt] = s[rt]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void change(int rt,int l,int r,int x,int v) { if(l==r) { maxx[rt] = minn[rt] = s[rt] = v; return ; } if(x<=mid) change(rt<<1,l,mid,x,v); else change(rt<<1|1,mid+1,r,x,v); up(rt); } void update(int rt,int l,int r,int x,int y,int v) { if(maxx[rt]<v) return; if(l==r) { int tmp = maxx[rt]%v; s[rt] = maxx[rt] = minn[rt] = tmp; return ; } if(x<=mid) update(rt<<1,l,mid,x,y,v); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v); up(rt); } ll query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return s[rt]; } ll res = 0; if(x<=mid) res+=query(rt<<1,l,mid,x,y); if(mid<y) res+=query(rt<<1|1,mid+1,r,x,y); return res; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y,v; scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) printf("%lld\n",query(1,1,n,x,y)); else if(opt==3) change(1,1,n,x,y); else { int v; scanf("%d",&v); update(1,1,n,x,y,v); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
019 HDU 6183
Actually, like CF19D, there are only 50 colors. You need to build 50 line segments to show others the code.
This is done by storing the minimum x of the color for each y coordinate.
The dynamic starting point deserves a good review
const int MAX_N = 1000025; int root[52]; int minn[MAX_N<<2],son[MAX_N<<2][2],cnt = 0; int Min(int a,int b){if(a<b) return a;return b;} inline void init() { memset(root,0,sizeof(root)); cnt = 0; son[0][0] = son[0][1] = 0; minn[0] = inf; } inline void up(int p) { minn[p] = min(minn[son[p][0]],minn[son[p][1]]); } inline void update(int &p,int l,int r,int x,int y) { if(!p) { p=++cnt; minn[p] = y; son[p][0] = son[p][1] = 0; } if(l==r) { minn[p] = min(minn[p],y); return ; } int mid = (l+r)>>1; if(x<=mid) update(son[p][0],l,mid,x,y); else update(son[p][1],mid+1,r,x,y); up(p); } inline int query(int p,int l,int r,int ql,int qr){ if(!p)return inf; if(ql<=l&&r<=qr)return minn[p]; int mid=l+r>>1; if(qr<=mid)return query(son[p][0],l,mid,ql,qr); if(ql>mid)return query(son[p][1],mid+1,r,ql,qr); return min(query(son[p][0],l,mid,ql,mid),query(son[p][1],mid+1,r,mid+1,qr)); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t,x,y,c; init(); while(~scanf("%d",&t)) { if(t==3) break; else if(t==0) init(); else if(t==1) { scanf("%d%d%d",&x,&y,&c); update(root[c],1,1000000,y,x); } else { scanf("%d%d%d",&x,&y,&c); int ans = 0; for(int i = 0;i<=50;++i) ans+=(query(root[i],1,1000000,y,c)<=x); printf("%d\n",ans); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
020 P1471
Interval plus Interval to Find Mean Interval to Find Variance
In fact, the key to this problem is to make the difference formula. You can get the final variance formula by listing each item.
(a[l]*a[l]+a[l+1]*a[l+1]+...a[r]*a[r])/(r-l+1) - ((a[l]+a[l+1]+...+a[r])/(r-l+1))^2
Then we just need to maintain a[i] square and a[i]
Then it can be realized by using segment tree to operate.
const int MAX_N = 100025; double s[MAX_N<<2],s_mul[MAX_N<<2],col[MAX_N<<2]; void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; s_mul[rt] = s_mul[rt<<1] + s_mul[rt<<1|1]; } void down(int rt,int l,int r) { if(col[rt]) { col[rt<<1] += col[rt]; col[rt<<1|1] += col[rt]; s_mul[rt<<1] += (s[rt<<1])*col[rt]*2+col[rt]*col[rt]*(mid-l+1); s_mul[rt<<1|1] += (s[rt<<1|1])*col[rt]*2+col[rt]*col[rt]*(r-mid); s[rt<<1] += (mid-l+1)*col[rt]; s[rt<<1|1] += (r-mid)*col[rt]; col[rt] = 0; } } void build(int rt,int l,int r) { s[rt] = s_mul[rt] = col[rt] = 0; if(l==r) { scanf("%lf",&s[rt]); s_mul[rt] = s[rt]*s[rt]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int y,double v) { if(x<=l&&r<=y) { s_mul[rt]+=v*(s[rt])*2+v*v*(r-l+1); s[rt]+=(r-l+1)*v; col[rt]+=v; return ; } down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y,v); if(mid<y) update(rt<<1|1,mid+1,r,x,y,v); up(rt); } double query(int rt,int l,int r,int x,int y,int v) { if(x<=l&&r<=y) { return (v==0?s[rt]:s_mul[rt]); } down(rt,l,r); if(y<=mid) return query(rt<<1,l,mid,x,y,v); if(mid<x) return query(rt<<1|1,mid+1,r,x,y,v); return query(rt<<1,l,mid,x,y,v)+query(rt<<1|1,mid+1,r,x,y,v); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,opt,x,y; double v; scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { scanf("%lf",&v); update(1,1,n,x,y,v); } else if(opt==2) { double ans = query(1,1,n,x,y,0)/(y-x+1); printf("%.4f\n",ans); } else { double ans = query(1,1,n,x,y,1)/(y-x+1) - query(1,1,n,x,y,0)/(y-x+1)*query(1,1,n,x,y,0)/(y-x+1); printf("%.4f\n",ans); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
021 Cogs 2964
Let's give you n-length b arrays, b arrays are all arranged in [1,n], and a arrays are initialized to 0 Q operations.
add l r
query l r
The add operation is to add the interval of an array to 1
Query operation is the a[i]b[i] of query l_r
The query operation is lfloor frac {a left [i right]} {b left [i right]} floor rfloor of the query l-r
Query operation is query l_r b[i]a[i]
Sample data:
input
5 12
1 5 2 4 3
add 1 4
query 1 4
add 2 5
query 2 5
add 3 5
query 1 5
add 2 4
query 1 4
add 2 5
query 2 5
add 2 2
query 1 5
output
1
1
2
4
4
6
practice
The first thing you think about is that the complexity of your violent change is n+n/2+n/3 +. 1 = lnn (harmonic series)
It's just a lot of maintenance.
In fact, in turn, you wonder why you want to change your point, because the current a[i]+1 is a multiple of b[i].
Does that mean a[i]%b[i] is one?
So as long as we maintain b[i] - a[i]%b[i], it means that the difference between b[i] and 1
In this way, we create a line segment tree and let num array jump with 1. If we reach a single point, the tree array is updated and num[rt] = b[l]
Because you're going to start the process again.
If num [rt] > 1, then you can subtract 1 from the direct interval.
The code is still beautiful.
int Min(int a,int b){if(a<b) return a;return b;} const int MAX_N = 100025; int num[MAX_N<<2],C[MAX_N<<1],col[MAX_N<<2],b[MAX_N]; void add(int x,int v) { for(;x<MAX_N;x+=x&(-x)) C[x]+=v; } int getsum(int x) { int res = 0; for(;x;x-=x&(-x)) res+=C[x]; return res; } void up(int rt) { num[rt] = Min(num[rt<<1],num[rt<<1|1]); } void down(int rt,int l,int r) { if(col[rt]) { col[rt<<1] += col[rt]; col[rt<<1|1] += col[rt]; num[rt<<1] += col[rt]; num[rt<<1|1] += col[rt]; col[rt] = 0; } } void build(int rt,int l,int r) { num[rt] = col[rt] = 0; if(l==r) { num[rt] = b[l]; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); return ; } void update(int rt,int l,int r,int x,int y) { if(l==r&&num[rt]==1) {num[rt]=b[l];add(l,1);return;} if(x<=l&&r<=y&&num[rt]>1) {col[rt]+=-1;num[rt]-=1;return;} down(rt,l,r); if(x<=mid) update(rt<<1,l,mid,x,y); if(mid<y) update(rt<<1|1,mid+1,r,x,y); up(rt); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q,x,y; char str[10]; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) scanf("%d",&b[i]); build(1,1,n); while(Q--) { scanf("%s%d%d",str,&x,&y); if(str[0]=='a') { update(1,1,n,x,y); } else { printf("%d\n",getsum(y)-getsum(x-1)); } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
022 HDU 5316
The title gives you a sequence of n elements
1 Operations to change the value of the 1st element to r ___________
0 operation finds that l to r satisfies the maximum sum of different parity of coordinates of each adjacent element in the original sequence in a sequence period
At first, my approach was to find the maximum continuous section with odd coordinates and the maximum continuous section with even coordinates and the sum of the two.
Later, I thought that the next topic could be added and disconnected, so my approach was obviously wrong.
We should maintain four things, that is, to merge the cases where the starting coordinates are even (odd) and the ending coordinates are even (odd).
Note that since the number of inputs may be - 1e9, we need to set our initial value to - 0x7fffffff.
const int inf = 0x7fffffff; const int MAX_N = 100025; ll Max(ll a,ll b){if(a>b) return a;return b;} struct node { ll lo,ll,ol,oo; }arr[MAX_N<<2]; void up(int rt) { arr[rt].ll = Max(Max(arr[rt<<1].lo+arr[rt<<1|1].ll,arr[rt<<1].ll+arr[rt<<1|1].ol),Max(arr[rt<<1].ll,arr[rt<<1|1].ll)); arr[rt].lo = Max(Max(arr[rt<<1].lo+arr[rt<<1|1].lo,arr[rt<<1].ll+arr[rt<<1|1].oo),Max(arr[rt<<1].lo,arr[rt<<1|1].lo)); arr[rt].ol = Max(Max(arr[rt<<1].oo+arr[rt<<1|1].ll,arr[rt<<1].ol+arr[rt<<1|1].ol),Max(arr[rt<<1].ol,arr[rt<<1|1].ol)); arr[rt].oo = Max(Max(arr[rt<<1].oo+arr[rt<<1|1].lo,arr[rt<<1].ol+arr[rt<<1|1].oo),Max(arr[rt<<1].oo,arr[rt<<1|1].oo)); } void build(int rt,int l,int r) { arr[rt].ll = arr[rt].lo = arr[rt].ol = arr[rt].oo = -inf; if(l==r) { ll v; scanf("%lld",&v); if(l%2==1) arr[rt].ll =v; else arr[rt].oo = v; return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void update(int rt,int l,int r,int x,int v) { if(l==r) { if(l%2==1) arr[rt].ll = 1ll*v; else arr[rt].oo = 1ll*v; return ; } if(x<=mid) update(rt<<1,l,mid,x,v); else update(rt<<1|1,mid+1,r,x,v); up(rt); } node query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return arr[rt]; } if(y<=mid) return query(rt<<1,l,mid,x,y); if(mid<x) return query(rt<<1|1,mid+1,r,x,y); node tmp1 = query(rt<<1,l,mid,x,y),tmp2 = query(rt<<1|1,mid+1,r,x,y),ans; ans.ll = Max(Max(tmp1.ll+tmp2.ol,tmp1.lo+tmp2.ll),Max(tmp1.ll,tmp2.ll)); ans.lo = Max(Max(tmp1.ll+tmp2.oo,tmp1.lo+tmp2.lo),Max(tmp1.lo,tmp2.lo)); ans.ol = Max(Max(tmp1.oo+tmp2.ll,tmp1.ol+tmp2.ol),Max(tmp1.ol,tmp2.ol)); ans.oo = Max(Max(tmp1.oo+tmp2.lo,tmp1.ol+tmp2.oo),Max(tmp1.oo,tmp2.oo)); return ans; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int t,n,Q,opt,x,y; ll v; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&Q); build(1,1,n); while(Q--) { scanf("%d%d%d",&opt,&x,&y); if(opt==1) { update(1,1,n,x,1ll*y); } else { node ans = query(1,1,n,x,y); printf("%lld\n",Max(Max(ans.ll,ans.lo),Max(ans.oo,ans.ol))); } } } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
023 CF 750 E
Give you n-length strings and then give you Q queries
The minimum number of characters deleted between Q input l and r question l and r can prevent 2016 from appearing in 2017.
practice
This problem is rather difficult (for me).
Let's consider this problem globally, regardless of how l and r globally seek the minimum deletion cost.
This problem is actually a previous one where we defined a two-dimensional dp array dp[5][5]
Represents five states 0 states 2 none
1 state 2
2 state 2 followed by 0
3 state has 201
4 states have 2017
The meaning of dp arrays is how many characters should be deleted to minimize the transition between states
It's just not 6, so when 6 appears, dp[3][3] and dp[4][4] are all 1.
How to update the dp value? The idea of matrix multiplication is just that multiplication becomes addition.
min represents the minimum number of characters that need to be deleted.
So we just output dp[0][4] and that's the answer.
const int MAX_N = 200025; char str[MAX_N]; int num[MAX_N]; struct node { int f[5][5]; void init(int x) { for(int i = 0;i<5;++i) for(int j = 0;j<5;++j) f[i][j]=(i==j?0:inf); if(x==-1) { for(int i = 0;i<5;++i) f[i][i] = inf; } else if(x==2) { f[0][0] = 1; f[0][1] = 0; } else if(x==0) { f[1][1] = 1; f[1][2] = 0; } else if(x==1) { f[2][2] = 1; f[2][3] = 0; } else if(x==7) { f[3][3] = 1; f[3][4] = 0; } else if(x==6) { f[3][3] = 1; f[4][4] = 1; } } }arr[MAX_N<<2]; node Merge(node a,node b) { node ret; ret.init(-1); for(int i = 0;i<5;++i) for(int j = 0;j<5;++j) for(int k = 0;k<5;++k) ret.f[i][j] = min(ret.f[i][j],a.f[i][k]+b.f[k][j]); return ret; } void build(int rt,int l,int r) { if(l==r) { arr[rt].init(num[l]); return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); arr[rt] = Merge(arr[rt<<1],arr[rt<<1|1]); } node query(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { return arr[rt]; } if(x>mid) return query(rt<<1|1,mid+1,r,x,y); if(y<=mid) return query(rt<<1,l,mid,x,y); node ans = Merge(query(rt<<1,l,mid,x,y),query(rt<<1|1,mid+1,r,x,y)); return ans; } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int x,y,n,Q; scanf("%d%d",&n,&Q); scanf("%s",str+1); for(int i = 1;i<=n;++i) num[i] = str[i]-'0'; build(1,1,n); while(Q--) { scanf("%d%d",&x,&y); node ans = query(1,1,n,x,y); printf("%d\n",ans.f[0][4]==inf?-1:ans.f[0][4]); } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
024 BZOJ 3747
meaning of the title
In fact, this practice was thought of in last year's provincial competition, but at that time, the team could only think of n^2 violence to test.
Today I meet again and actually talk about it.
We maintain a prearray to represent the subscript that appeared before that number.
The first thing we know about a movie is that the range of contributions it can make is pre[i]+1 to I.
This is the first interval plus operation.
So are we going to cancel the contribution of the last movie?
It's pre [pre[i] + 1 to pre[i] that subtracts these contributions.
In this way, we can enumerate the right endpoint with n in the outer layer and use the segment tree to optimize it, then we can get the maximum answer.
ll Max(ll a,ll b){if(a>b) return a;return b;} const int MAX_N = 1000025; int arr[MAX_N],last[MAX_N],pre[MAX_N]; ll val[MAX_N],maxx[MAX_N<<2],col[MAX_N<<2]; void up(int rt) { maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]); } void down(int rt,int l,int r) { if(col[rt]) { col[rt<<1] += col[rt]; col[rt<<1|1] += col[rt]; maxx[rt<<1] += col[rt]; maxx[rt<<1|1] += col[rt]; col[rt] = 0; } } void update(int rt,int l,int r,int x,int y,ll v) { if(x<=l&&r<=y) { col[rt] += v; maxx[rt] += v; return ; } down(rt,l,r); if(y<=mid) update(rt<<1,l,mid,x,y,v); else if(x>mid) update(rt<<1|1,mid+1,r,x,y,v); else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v); up(rt); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,m; ll ans = 0; scanf("%d%d",&n,&m); for(int i = 1;i<=n;++i) scanf("%d",&arr[i]); for(int i = 1;i<=m;++i) scanf("%d",&val[i]); for(int i = 1;i<=n;++i) pre[i] = last[arr[i]],last[arr[i]] = i; for(int i = 1;i<=n;++i) { update(1,1,n,pre[i]+1,i,val[arr[i]]); if(pre[i]) update(1,1,n,pre[pre[i]]+1,pre[i],-val[arr[i]]); ans = Max(ans,maxx[1]); } printf("%lld\n",ans); //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }
025 BZOJ 4293
Title: There is an area of n mu of land on which grass should be planted. Each grass grows a[i] centimeter at a time
There are Q operations d v representing all the grass that is higher than V at the end of the second at D time.
What shall we do? The first thing to discover is a nature (kneeling).
It's when you first sort a[i] in order that a[i] is monotonous in any way.
So we just need to find the first position greater than v, POS to n interval covering V every time.
Then the difference between s[1] before and s[1] after interval coverage is the answer.
Here setv stands for the replacement label col for the lazy label and the time it takes to download it is how many days the grass grows.
Interval Covering and Interval Adding Covering First Because Adding Re-Covering is Equivalent to Direct Covering
const int MAX_N = 500025; ll maxx[MAX_N<<2],s[MAX_N<<2],setv[MAX_N<<2],col[MAX_N<<2],sum[MAX_N],arr[MAX_N]; ll Max(ll a,ll b){if(a>b) return a;return b;} void up(int rt) { s[rt] = s[rt<<1] + s[rt<<1|1]; maxx[rt] = Max(maxx[rt<<1],maxx[rt<<1|1]); } void build(int rt,int l,int r) { setv[rt] = -1;col[rt] = s[rt] = maxx[rt] = 0; if(l==r) { return ; } build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); up(rt); } void down(int rt,int l,int r) { if(setv[rt]!=-1) { setv[rt<<1] = setv[rt<<1|1] = setv[rt]; maxx[rt<<1] = maxx[rt<<1|1] = setv[rt]; s[rt<<1] = 1ll*(mid-l+1)*setv[rt]; s[rt<<1|1] = 1ll*(r-mid)*setv[rt]; col[rt<<1] = col[rt<<1|1] = 0; setv[rt] = -1; } if(col[rt]) { maxx[rt<<1] += col[rt]*arr[mid]; maxx[rt<<1|1] += col[rt]*arr[r]; s[rt<<1] += col[rt]*(sum[mid]-sum[l-1]); s[rt<<1|1] += col[rt]*(sum[r]-sum[mid]); col[rt<<1]+=col[rt]; col[rt<<1|1] += col[rt]; col[rt] = 0; } } /*inline void pushnow(int p,ll v){T[p].sum+=v*(sum[T[p].r]-sum[T[p].l-1]),T[p].maxn+=v*a[T[p].r],T[p].lz+=v;} inline void pushnown(int p,ll v){T[p].bz=v,T[p].lz=0,T[p].sum=(T[p].r-T[p].l+1)*v,T[p].maxn=v;} inline void pushdown(int p){ if(T[p].bz!=-1)pushnown(lc,T[p].bz),pushnown(rc,T[p].bz),T[p].bz=-1; if(T[p].lz)pushnow(lc,T[p].lz),pushnow(rc,T[p].lz),T[p].lz=0; }*/ void update(int rt,int l,int r,int x,int y,ll v) { if(x<=l&&r<=y) { setv[rt] = v; maxx[rt] = v; s[rt] = 1ll*(r-l+1)*v; col[rt] = 0; return ; } down(rt,l,r); if(y<=mid) update(rt<<1,l,mid,x,y,v); else if(x>mid) update(rt<<1|1,mid+1,r,x,y,v); else update(rt<<1,l,mid,x,y,v),update(rt<<1|1,mid+1,r,x,y,v); up(rt); } int query(int rt,int l,int r,ll v) { if(l==r) { return l; } down(rt,l,r); if(maxx[rt<<1]>v) return query(rt<<1,l,mid,v); else return query(rt<<1|1,mid+1,r,v); } int main() { //ios::sync_with_stdio(false); //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); int n,Q; scanf("%d%d",&n,&Q); for(int i = 1;i<=n;++i) scanf("%lld",&arr[i]); build(1,1,n); sort(arr+1,arr+1+n); for(int i = 1;i<=n;++i) sum[i] = sum[i-1] + arr[i]; ll d1 = 0,d2,v; while(Q--) { scanf("%lld%lld",&d2,&v); s[1] += sum[n]*(d2-d1),maxx[1] += (d2-d1)*arr[n],col[1]+=(d2-d1); ll tmp = s[1]; if(maxx[1]<=v) {d1 = d2;printf("0\n");continue;} d1 = d2; int pos = query(1,1,n,v); update(1,1,n,pos,n,v); printf("%lld\n",tmp-s[1]); } //fclose(stdin); //fclose(stdout); //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl; return 0; }