【学习】线段树
感觉自己虽然在学习树剖的时候学习了线段树(这什么学习过程?
但是感觉自己还有很多姿势不够
所以先做几道题吧
No. | 算法 | 状态 |
---|---|---|
1012 | 树状数组/线段树/RMQ | Accepted |
1798 | 线段树 | Accepted |
3212 | Splay/线段树区间操作 | Accepted |
3226 | 线段树 | Accepted |
4364 | 线段树 | Accepted |
3685 | 线段树 | Accepted |
3813 | 线段树+逆元 | Accepted |
2962 | 线段树 | Accepted |
1067 | 线段树分类讨论 | Accepted |
4373 | 线段树 | Accepted |
1858 | 线段树各种操作 | Accepted |
update20170112: 新增一道各种操作的题目:BZOJ1858
update20161108: 修修补补地到了10题
竟然才做了9道QAQ
连两位数都没上 羞耻.jpg
1012: [JSOI2008]最大数maxnumber
比较简单的线段树吧
也没有太复杂的标记什么的
真是简单粗暴
听说还有单调栈和单调队列的做法,真刺激
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #define MM 200020 using namespace std; char ch[10]; int mx[MM*4],a[MM]; int la,l,n,m,t,d,mm; void change(int ll,int rr,int st) { if (ll==rr) { mx[st]=n; return; } int mid=(ll+rr)/2; if (l<=mid) change(ll,mid,st<<1); else change(mid+1,rr,(st<<1)+1); mx[st]=max(mx[st<<1],mx[(st<<1)+1]); return; } int check(int ll,int rr,int l,int r,int st) { if (ll<=l&&rr>=r) return mx[st]; int sum=0,mid=(l+r)/2; if (ll<=mid) sum=max(sum,check(ll,rr,l,mid,st<<1)); if (rr>mid) sum=max(sum,check(ll,rr,mid+1,r,(st<<1)+1)); return sum; } int main() { scanf("%d%d",&m,&d); t=l=0; mm=m; memset(mx,0,sizeof(mx)); while (m--) { scanf("%s%d",&ch,&n); l++; if (ch[0]=='A') { a[++la]=l; n=(n%d+t%d)%d; change(1,mm,1); } else { printf("%d\n",t=check(a[la-n+1],a[la],1,mm,1)); t%=d; } } return 0; }
1798: [Ahoi2009]Seq 维护序列seq
其实和黈力上课讲的某一题差不多的吧
但标记不能永久化
要维护两个tag
调的累炸了
听说窝的程序跑得比xmc快?!(但人家的程序短啊!
#include <iostream> #include <cmath> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> using namespace std; #define NN 100005 #define LL long long struct Tree { int l,r; LL t1,t2,sum; }tr[NN<<2]; int n,m,mod,op,l,r,x,a[NN]; void Build(int p,int l,int r) { tr[p].l = l, tr[p].r = r, tr[p].t1 = 0, tr[p].t2 = 1; if (l == r) { tr[p].sum = a[l] % mod; return; } int mid = (l+r) >> 1; Build(p<<1,l,mid); Build(p<<1|1,mid+1,r); tr[p].sum = (tr[p<<1].sum + tr[p<<1|1].sum) % mod; } void push_down(int num) { if (tr[num].t2==1&&tr[num].t1==0) return; tr[num*2].t1=(tr[num*2].t1*tr[num].t2+tr[num].t1)%mod; tr[num*2+1].t1=(tr[num*2+1].t1*tr[num].t2+tr[num].t1)%mod; tr[num*2].t2=(tr[num*2].t2*tr[num].t2)%mod; tr[num*2+1].t2=(tr[num*2+1].t2*tr[num].t2)%mod; tr[num*2].sum=(tr[num*2].sum*tr[num].t2+(tr[num*2].r-tr[num*2].l+1)*tr[num].t1)%mod; tr[num*2+1].sum=(tr[num*2+1].sum*tr[num].t2+(tr[num*2+1].r-tr[num*2+1].l+1)*tr[num].t1)%mod; tr[num].t1=0; tr[num].t2=1; return; } void mul(int p,int l,int r,int xx) { if (tr[p].l > r || tr[p].r < l) return; if (tr[p].l >= l && tr[p].r <= r) { tr[p].t1 = tr[p].t1 * xx % mod; tr[p].t2 = tr[p].t2 * xx % mod; tr[p].sum = tr[p].sum * xx % mod; return; } push_down(p); mul(p<<1,l,r,xx); mul(p<<1|1,l,r,xx); tr[p].sum = (tr[p<<1].sum + tr[p<<1|1].sum) % mod; return; } void add(int p,int l,int r,int xx) { if (tr[p].l > r || tr[p].r < l) return; if (tr[p].l >= l && tr[p].r <= r) { tr[p].t1 = (tr[p].t1 + xx) % mod; tr[p].sum = (tr[p].sum + (tr[p].r - tr[p].l + 1)*xx % mod) % mod; return; } push_down(p); add(p<<1,l,r,xx); add(p<<1|1,l,r,xx); tr[p].sum = (tr[p<<1].sum + tr[p<<1|1].sum) % mod; return; } LL query(int p,int l,int r) { if (tr[p].l > r || tr[p].r < l) return 0; if (tr[p].l >= l && tr[p].r <= r) return tr[p].sum % mod; push_down(p); return (query(p<<1,l,r) + query(p<<1|1,l,r)) % mod; } int main() { scanf("%d%d",&n,&mod); for (int i=1;i<=n;++i) scanf("%d",&a[i]); Build(1,1,n); scanf("%d",&m); while (m--) { scanf("%d",&op); switch (op) { case 1: scanf("%d%d%d",&l,&r,&x); mul(1,l,r,x); break; case 2: scanf("%d%d%d",&l,&r,&x); add(1,l,r,x); break; case 3: scanf("%d%d",&l,&r); printf("%d\n",query(1,l,r)%mod); break; } } return 0; }
3212: Pku3468 A Simple Problem with Integers
维护线段树,区间加,区间求和
注意long long
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <cstdlib> using namespace std; #define LL long long #define NN 100005 int n,m,x,y,z; char ch[10]; struct Tree { LL s,ad; int l,r; }tr[NN<<2]; void push_up(int p) { tr[p].s = tr[p<<1].s + tr[p<<1|1].s; } void push_down(int p) { if (tr[p].l == tr[p].r) return; if (tr[p].ad) { tr[p<<1].ad += tr[p].ad, tr[p<<1|1].ad += tr[p].ad; tr[p<<1].s += tr[p].ad * (tr[p<<1].r - tr[p<<1].l + 1); tr[p<<1|1].s += tr[p].ad * (tr[p<<1|1].r - tr[p<<1|1].l + 1); tr[p].ad = 0; } } void Build(int p,int l,int r) { tr[p].l = l, tr[p].r = r; if (l == r) { scanf("%lld",&tr[p].s); return;} int mid = (l+r) >> 1; Build(p<<1,l,mid); Build(p<<1|1,mid+1,r); push_up(p); } void Add(int p,int L,int R,int v) { push_down(p); int l = tr[p].l, r = tr[p].r, sum = (r-l+1), mid = (l+r) >> 1; if (l == L && R == r) { tr[p].s += (LL) v * sum, tr[p].ad += v; return; } if (mid >= R) Add(p<<1,L,R,v); else if (mid < L) Add(p<<1|1,L,R,v); else Add(p<<1,L,mid,v), Add(p<<1|1,mid+1,R,v); push_up(p); } LL Query(int p,int L,int R) { push_down(p); int l = tr[p].l, r = tr[p].r, mid = (l+r) >> 1; if (l == L && R == r) return tr[p].s; if (mid >= R) return Query(p<<1,L,R); else if (mid < L) return Query(p<<1|1,L,R); else return Query(p<<1,L,mid) + Query(p<<1|1,mid+1,R); } int main() { scanf("%d%d",&n,&m); Build(1,1,n); while (m--) { scanf("%s",ch); if (ch[0] == 'Q') { scanf("%d%d",&x,&y); printf("%lld\n",Query(1,x,y)); } else { scanf("%d%d%d",&x,&y,&z); Add(1,x,y,z); } } return 0; }
3226: [Sdoi2008]校门外的区间
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; char ch[10]; #define N 131073 struct Tree { int l,r,val,tag,rev; }tr[N<<2]; int x,y,st,la,flag; int read() { int x=0,f=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='(')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} if(ch==')')f=1; return x*2-f; } void Build(int p,int l,int r) { tr[p].l = l, tr[p].r = r, tr[p].tag = -1; if (l == r) return; int mid = (l+r) >> 1; Build(p<<1,l,mid); Build(p<<1|1,mid+1,r); } void push_down(int p) { int tag = tr[p].tag, rev = tr[p].rev; tr[p].tag = -1, tr[p].rev = 0; if (tr[p].l == tr[p].r) { if (tag != -1) tr[p].val = tag; tr[p].val ^= rev; return; } if (tag != -1) { tr[p<<1].tag = tr[p<<1|1].tag = tag; tr[p<<1].rev = tr[p<<1|1].rev = 0; } tr[p<<1].rev ^= rev, tr[p<<1|1].rev ^= rev; } int Query(int p,int xx) { push_down(p); int l = tr[p].l, r = tr[p].r, mid = (l+r) >> 1; if (l == r) return tr[p].val; if (xx<=mid) return Query(p<<1,xx); else return Query(p<<1|1,xx); } void Modify(int p,int L,int R,int v) { if (R<L) return; push_down(p); int l = tr[p].l, r = tr[p].r, mid = (l+r) >> 1; if (l == L && R == r) { if (v == -1) tr[p].rev ^= 1; else tr[p].tag = v; return; } if (R <= mid) Modify(p<<1,L,R,v); else if (L > mid) Modify(p<<1|1,L,R,v); else Modify(p<<1,L,mid,v), Modify(p<<1|1,mid+1,R,v); } void Rev(int p,int L,int R) { Modify(p,L,R,-1);} int main() { Build(1,1,N); while (scanf("%s",ch) != EOF) { x = read(), y = read(); x += 2; y += 2; switch (ch[0]) { case 'U': Modify(1,x,y,1); break; case 'I': Modify(1,1,x-1,0); Modify(1,y+1,N,0); break; case 'D': Modify(1,x,y,0); break; case 'C': Modify(1,1,x-1,0); Modify(1,y+1,N,0); Rev(1,x,y); break; case 'S': Rev(1,x,y); break; } } st = la = -1; flag = 0; for (int i=1;i<=N;++i) if (Query(1,i)) { if (st == -1) st = i; la = i; } else { if (st != -1) { if (flag) printf(" "); else flag = 1; if (st & 1) printf("("); else printf("["); printf("%d,%d",st/2-1,(la+1)/2-1); if (la & 1) printf(")"); else printf("]"); } la = st = -1; } if (!flag) puts("empty set"); return 0; }
4364: [IOI2014]wall砖墙
线段树乱搞..乱更新一下QAQ
#include <iostream> #include <cstdio> #include <cmath> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define NN 2000010 int n,m,op,l,r,x,mx1[NN<<2],mx2[NN<<2]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void push_down(int p) { int l = p<<1, r = p<<1|1; if (mx2[p] > mx1[l]) mx1[l] = mx2[l] = mx2[p]; else if (mx2[p] > mx2[l]) mx2[l] = mx2[p]; if (mx2[p] > mx1[r]) mx1[r] = mx2[r] = mx2[p]; else if (mx2[p] > mx2[r]) mx2[r] = mx2[p]; if (mx1[p] < mx2[l]) mx1[l] = mx2[l] = mx1[p]; else if (mx1[p] < mx1[l]) mx1[l] = mx1[p]; if (mx1[p] < mx2[r]) mx1[r] = mx2[r] = mx1[p]; else if (mx1[p] < mx1[r]) mx1[r] = mx1[p]; } inline void push_up(int p) { mx1[p] = max(mx1[p<<1],mx1[p<<1|1]); mx2[p] = min(mx2[p<<1],mx2[p<<1|1]); } inline void Update1(int L,int R,int l,int r,int p,int xx) { if (L == l && R == r) { mx1[p] = max(mx1[p],xx), mx2[p] = max(mx2[p],xx); return;} int mid = (l+r) >> 1; push_down(p); if (R <= mid) Update1(L,R,l,mid,p<<1,xx); else if (L > mid) Update1(L,R,mid+1,r,p<<1|1,xx); else Update1(L,mid,l,mid,p<<1,xx), Update1(mid+1,R,mid+1,r,p<<1|1,xx); push_up(p); } inline void Update2(int L,int R,int l,int r,int p,int xx) { if (L == l && R == r) { mx1[p] = min(mx1[p],xx), mx2[p] = min(mx2[p],xx); return;} int mid = (l+r) >> 1; push_down(p); if (R <= mid) Update2(L,R,l,mid,p<<1,xx); else if (L > mid) Update2(L,R,mid+1,r,p<<1|1,xx); else Update2(L,mid,l,mid,p<<1,xx), Update2(mid+1,R,mid+1,r,p<<1|1,xx); push_up(p); } inline void Build(int p,int l,int r) { if (l == r) { printf("%d\n",mx1[p]); return; } int mid = (l+r) >> 1; push_down(p); Build(p<<1,l,mid), Build(p<<1|1,mid+1,r); } int main() { n = read(), m = read(); while (m--) { op = read(); if (op == 1) { l = read(), r = read(), x = read(); ++l ,++r; Update1(l,r,1,n,1,x); } else { l = read(), r = read(), x = read(); ++l ,++r; Update2(l,r,1,n,1,x); } } Build(1,1,n); return 0; }
3685: 普通van Emde Boas树
听说某Treap会被卡(反正不会写
糊里糊涂学习了一下zkw线段树的技巧 并没有完全弄会哎
在题解的帮助下终于写好了
#include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <cstdlib> #include <iostream> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,x,M = 0,cnt = 0,op; bool tr[1<<21|1]; inline void Update(int xx,int d) { if (!(d ^ tr[xx+M])) return; cnt += d ? 1 : -1; for (tr[xx+=M] = d, xx >>= 1;xx;xx >>= 1) tr[xx] = tr[xx<<1] | tr[xx<<1|1]; } inline int Get_min(int xx) { if (!cnt) return 0; for (;xx <= M;xx = tr[xx<<1] ? (xx<<1) : (xx<<1|1)); return xx - M; } inline int Get_max(int xx) { if (!cnt) return 0; for (;xx <= M;xx = tr[xx<<1|1] ? (xx<<1|1) : (xx<<1)); return xx - M; } inline int Pre(int xx) { if (!cnt) return 0; for (xx += M;xx != 1;xx >>= 1) if (xx & 1 && tr[xx^1]) { xx ^= 1; break; } if (xx == 1) return 0; return Get_max(xx); } inline int Nxt(int xx) { if (!cnt) return 0; for (xx += M;xx != 1;xx >>= 1) if (!(xx & 1) && tr[xx^1]) { xx ^= 1; break; } if (xx == 1) return 0; return Get_min(xx); } inline void Judge(int xx) { printf(tr[xx+M] ? "1\n" : "-1\n"); } int main() { n = read(), m = read(); while ((1<<M) < n) M++; M = (1<<M) - 1; for (int i=1;i<=m;++i) { op = read(); switch (op) { case 1: x = read() + 1; Update(x,1); break; case 2: x = read() + 1; Update(x,0); break; case 3: printf("%d\n",Get_min(1)-1); break; case 4: printf("%d\n",Get_max(1)-1); break; case 5: x = read() + 1; printf("%d\n",Pre(x) - 1); break; case 6: x = read() + 1; printf("%d\n",Nxt(x) - 1); break; case 7: x = read() + 1; Judge(x); break; } } return 0; }
3813: 奇数国
感觉乱七八糟的东西捏在一起就会好烦啊呜呜呜
并不喜欢想怎么弄标记,然而不想怎么弄标记就做不出题呜呜呜
用两棵线段树,一棵维护乘积,一棵维护质因数(类似于状压压起来
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } #define N 305 #define mod 19961993 #define LL long long LL bin[65],ni[N]; int n,pri[N]={0}; bool mark[N]={0}; struct Tree { int l,r; LL v; }tr[2][400010]; void Cal(int f,int k,int val) { if (f == 0) tr[f][k].v = val; else { tr[f][k].v = 0; for (int i=1;i<=60;++i) if (val % pri[i] == 0) tr[f][k].v += bin[i-1]; } } void update(int f,int p) { if (f == 0) tr[f][p].v = tr[f][p<<1].v * tr[f][p<<1|1].v % mod; else tr[f][p].v = tr[f][p<<1].v | tr[f][p<<1|1].v; } void Build(int f,int p,int l,int r) { tr[f][p].l = l, tr[f][p].r = r; int mid = (l+r) >> 1; if (l == r) { Cal(f,p,3); return; } Build(f,p<<1,l,mid), Build(f,p<<1|1,mid+1,r); update(f,p); } void Pre() { ni[1] = 1; for (int i=2;i<=300;++i) { ni[i] = -mod/i * ni[mod%i] % mod; if (!mark[i]) pri[++pri[0]] = i; for (int j=1;j<=pri[0] && i*pri[j]<=300;++j) { mark[i*pri[j]] = 1; if (i%pri[j] == 0) break; } } bin[0] = 1; for (int i=1;i<=60;++i) bin[i] = bin[i-1] << 1; Build(0,1,1,100000); Build(1,1,1,100000); } LL que(int f,int p,int x,int y) { int l = tr[f][p].l, r = tr[f][p].r, mid = (l+r) >> 1; if (l == x && r == y) return tr[f][p].v; if (y<=mid) return que(f,p<<1,x,y); else if (x > mid) return que(f,p<<1|1,x,y); else { if (f == 0) return que(f,p<<1,x,mid) * que(f,p<<1|1,mid+1,y) % mod; else return que(f,p<<1,x,mid) | que(f,p<<1|1,mid+1,y); } } int Query(int xx,int yy) { LL tmp1 = que(0,1,xx,yy), tmp2 = que(1,1,xx,yy); for (int i=1;i<=60;++i) if (tmp2 & bin[i-1]) tmp1 = tmp1*(pri[i]-1) % mod * ni[pri[i]] %mod; tmp1 = (tmp1 + mod) % mod; return tmp1; } void Change(int f,int p,int xx,int val) { int l = tr[f][p].l ,r = tr[f][p].r, mid = (l+r) >>1; if (l == r) { Cal(f,p,val); return; } if (xx<=mid) Change(f,p<<1,xx,val); else Change(f,p<<1|1,xx,val); update(f,p); } int main() { Pre(); n = read(); for (int i=1;i<=n;++i) { int op = read(), x = read(), y = read(); if (op == 0) printf("%d\n",Query(x,y)); else Change(0,1,x,y), Change(1,1,x,y); } return 0; }
2962: 序列操作
调得崩溃啊
最后错在把 p<<1|1 打成了p<<1 要死
用f[i]表示选i个数所有方案和,rt.f[i]=∑ij=0 ls.f[j] ∗ rs.f[i−j]
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; #define NN 60050 #define mod 19940417 #define LL long long int a[NN],b[25],c[NN][25],add[NN<<2],rev[NN<<2]; int n,q,x,y,z; char ch[10]; struct Tree { int f[25]; }tr[NN<<2]; int read() { bool f; char ch; int x; for (f=0,ch=getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=1; for (x=0;ch>='0';ch=getchar()) x=x*10+ch-'0'; if (f) x=-x; return x; } void Update(int &xx,int yy) { xx += yy; if (xx >= mod) xx -= mod; if (xx < 0) xx += mod; } void Cal(int p,int l,int r,int xx) { for (int i=1;i<=20;++i) { int tmp =0, tx = 1; for (int j=i;j>=0;--j) { Update(tmp,(LL)tr[p].f[j] * c[r-l+1-j][i-j] % mod * tx %mod); tx = (LL) tx * xx % mod; } b[i] = tmp; } for (int i=1;i<=20;++i) tr[p].f[i] = b[i]; } void push_down(int p,int l,int r) { if (rev[p]) { rev[p<<1] ^= 1, rev[p<<1|1] ^= 1; for (int i=1;i<=20;i+=2) tr[p<<1].f[i] = (mod - tr[p<<1].f[i]) % mod; for (int i=1;i<=20;i+=2) tr[p<<1|1].f[i] = (mod - tr[p<<1|1].f[i]) % mod; add[p<<1] = (mod - add[p<<1]) % mod, add[p<<1|1] = (mod - add[p<<1|1]) % mod; rev[p] = 0; } if (add[p]) { int mid = (l+r) >> 1; Update(add[p<<1],add[p]), Update(add[p<<1|1],add[p]); Cal(p<<1,l,mid,add[p]), Cal(p<<1|1,mid+1,r,add[p]); add[p] = 0; } } void push_up(int p) { for (int i=1;i<=20;++i) tr[p].f[i] = 0; for (int i=0;i<=20;++i) for (int j=0;i+j <= 20;++j) { if (i+j == 0) continue; Update(tr[p].f[i+j],(LL)tr[p<<1].f[i] * tr[p<<1|1].f[j] % mod); } } void Build(int p,int l,int r) { tr[p].f[0] = 1; if (l == r) { tr[p].f[1] = a[l]; return; } int mid = (l+r) >> 1; Build(p<<1,l,mid), Build(p<<1|1,mid+1,r); push_up(p); } void Inc(int p,int l,int r,int L,int R,int x) { if (L <= l && R >= r) { Update(add[p],x); Cal(p,l,r,x); return; } int mid = (l+r) >> 1; push_down(p,l,r); if (L <= mid) Inc(p<<1,l,mid,L,R,x); if (R > mid) Inc(p<<1|1,mid+1,r,L,R,x); push_up(p); } void Rev(int p,int l,int r,int L,int R) { if (L <= l && R >= r) { rev[p] ^= 1; add[p] = (mod - add[p]) % mod; for (int i=1;i<=20;i+=2) tr[p].f[i] = (mod - tr[p].f[i]) % mod; return; } int mid = (l+r) >> 1; push_down(p,l,r); if (L <= mid) Rev(p<<1,l,mid,L,R); if (R > mid) Rev(p<<1|1,mid+1,r,L,R); push_up(p); } Tree Ask(int p,int l,int r,int L,int R) { if (L <= l && R >= r) return tr[p]; push_down(p,l,r); int mid = (l+r) >>1; Tree t,t1,t2; if (L > mid) t = Ask(p<<1|1,mid+1,r,L,R); else if (R <= mid) t = Ask(p<<1,l,mid,L,R); else { t.f[0] = 1; for (int i=1;i<=20;++i) t.f[i] = 0; t1 = Ask(p<<1,l,mid,L,mid), t2 = Ask(p<<1|1,mid+1,r,mid+1,R); for (int i=0;i<=20;++i) for (int j=0;j+i <= 20;++j) { if (i+j == 0) continue; Update(t.f[i+j],(LL)t1.f[i] * t2.f[j] % mod); } } return t; } int main() { n = read(), q = read(); for (int i=0;i<=n;++i) { c[i][0] = c[i][i] = 1; for (int j=1;j<i;++j) c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod; } for (int i=1;i<=n;++i) a[i] = read(), a[i] = (a[i] % mod + mod) %mod; Build(1,1,n); while (q--) { scanf("%s",ch); if (ch[0] == 'I') { x = read(), y =read(), z = read(); z = (z%mod+mod)%mod; Inc(1,1,n,x,y,z); } else if (ch[0] == 'R') { x = read(), y = read(); Rev(1,1,n,x,y); } else { x = read(), y = read(), z = read(); z = (z%mod+mod)%mod; Tree tmp = Ask(1,1,n,x,y); printf("%d\n",tmp.f[z] % mod); } } return 0; }
1067: [SCOI2007]降雨量
错误有危险,分类需谨慎
分类讨论都有毒,剧毒
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <queue> #include <algorithm> #define lk k<<1 #define rk k<<1|1 using namespace std; int n,m; struct TREE { int ly,ry,mx,f; }tr[200001]; void read(int &xx) { bool f=0; char CH; for (CH=getchar();CH<'0'||CH>'9';CH=getchar()) if (CH=='-') f=1; for (xx=0;CH>='0';CH=getchar()) xx=xx*10+CH-'0'; if (f) xx=-xx; } void Build(int k,int l,int r) { if (l==r) { read(tr[k].ly), read(tr[k].mx); tr[k].ry=tr[k].ly; tr[k].f=1; return; } int mid=(l+r)>>1; Build(lk,l,mid), Build(rk,mid+1,r); tr[k].f=(tr[lk].f && tr[rk].f); if (tr[lk].ry+1!=tr[rk].ly) tr[k].f=0; tr[k].ly=tr[lk].ly, tr[k].ry=tr[rk].ry, tr[k].mx=max(tr[lk].mx,tr[rk].mx); } int Get(int k,int xx) { if (tr[k].ly==tr[k].ry) { if (tr[k].ly!=xx) return 0; else return tr[k].mx; } if (xx<=tr[lk].ry) return Get(lk,xx); else if (xx>=tr[rk].ly) return Get(rk,xx); return 0; } int Getne(int k,int xx) { int l=tr[k].ly, r=tr[k].ry; if (l==r) return tr[k].ly; if (xx<tr[lk].ry) return Getne(lk,xx); else return Getne(rk,xx); } int Getla(int k,int xx) { int l=tr[k].ly, r=tr[k].ry; if (l==r) return tr[k].ly; if (xx>tr[rk].ly) return Getla(rk,xx); else return Getla(lk,xx); } int Ask(int k,int xx,int yy,int num) { bool flag=0; if (xx<tr[k].ly) flag=1, xx=tr[k].ly; if (tr[k].ly==xx & tr[k].ry==yy) { if (tr[k].mx>=num) return 0; else if (tr[k].f&& !flag) return 1; else return 2; } if (yy<=tr[lk].ry) { return Ask(lk,xx,yy,num);} else if (xx>=tr[rk].ly) { return Ask(rk,xx,yy,num);} else { int ta=Ask(lk,xx,tr[lk].ry,num); int tb=Ask(rk,tr[rk].ly,yy,num); if (!ta || !tb) return 0; else if (tr[lk].ry+1 != tr[rk].ly) return 2; else return 1; } } int main() { read(n); Build(1,1,n); read(m); int ll,rr; for (int i=1;i<=m;++i) { read(ll), read(rr); if (rr<ll) { puts("false"); continue;} int lnum=Get(1,ll), rnum=Get(1,rr); if (!lnum && !rnum) { puts("maybe"); continue; } else { int st=Getne(1,ll), en=Getla(1,rr); if (!lnum) { if (st>en || rr==en) { puts("maybe"); continue; } int flag=Ask(1,st,en,rnum); if (!flag) puts("false"); else puts("maybe"); continue; } else if (!rnum) { if (st>en || ll==st) { puts("maybe"); continue; } int flag=Ask(1,st,en,lnum); if (!flag) puts("false"); else puts("maybe"); continue; } else { if (rnum>lnum) { puts("false"); continue;} if (st>en) {if (ll+1==rr) puts("true"); else puts("maybe"); continue;} int flag=Ask(1,st,en,rnum); if (!flag) puts("false"); else if (flag==1) { if (ll+1==st && rr-1==en) puts("true"); else puts("maybe"); } else if (flag==2) puts("maybe"); else puts("false"); } } } return 0; }
4373: 算术天才⑨与等差数列
在观摩了各种gcd做法后选择死亡
然后意外发现了一片净土
预处理区间和&平方和(需取模)&min 判断是否符合要求
感觉画风清奇
不被long long 搞死就可以了
(WA了四五发就是被long long搞死的TAT)
#include <bits/stdc++.h> using namespace std; typedef long long LL; #define lk k<<1 #define rk k<<1|1 const LL mod = 1000000009, SIX = 833333341; //SIX为6的逆元 const int NN = 300005,INF = 0x3f3f3f3f; struct TR { LL s1,s2,mn; }tr[NN<<2]; int n,m,op,x,y,z,cnt=0; LL a[NN]; bool flag; LL ksm(LL xx,LL yy) { LL sum=1ll; for (xx%=mod;yy;xx=xx*xx%mod,yy>>=1) if (yy&1) sum=sum*xx%mod; return sum; } void push_up(int k) { tr[k].s1 = tr[lk].s1 + tr[rk].s1; tr[k].s2 = (tr[lk].s2 + tr[rk].s2) % mod; tr[k].mn = min(tr[lk].mn,tr[rk].mn); } void Build(int k,int l,int r) { if (l == r) { tr[k].s1 = tr[k].mn = a[l]; tr[k].s2 = a[l] * a[l] % mod; return; } int mid = (l+r) >> 1; Build(lk,l,mid), Build(rk,mid+1,r); push_up(k); } void Change(int k,int l,int r,int p,LL v) { if (l == r) { tr[k].s1 = tr[k].mn = v; tr[k].s2 = v*v % mod; return; } int mid = (l+r) >> 1; if (p <= mid) Change(lk,l,mid,p,v); else Change(rk,mid+1,r,p,v); push_up(k); } LL Query(int k,int l,int r,int L,int R,int t) { if (L<=l && R>=r) { if (t == 1) return tr[k].s1; else return tr[k].s2; } int mid = (l+r) >> 1; LL pre = 0ll; if (L <= mid) pre += Query(lk,l,mid,L,R,t); if (R > mid) pre += Query(rk,mid+1,r,L,R,t); if (t == 2) pre %= mod; return pre; } LL Query_min(int k,int l,int r,int L,int R) { if (L<=l && R>=r) return tr[k].mn; int mid = (l+r) >> 1; LL pre = INF; if (L <= mid) pre = min(pre,Query_min(lk,l,mid,L,R)); if (R > mid) pre = min(pre,Query_min(rk,mid+1,r,L,R)); return pre; } LL Get1(LL x,LL l,LL k) { return x * l + (l - 1) * l / 2 * k; } LL Get2(LL x,LL l,LL k) { LL ret = x * x % mod * l % mod; ret = (ret + (l - 1) * l % mod * k % mod * x % mod) % mod; ret += l * (l - 1) % mod * (2 * l - 1) % mod * k % mod * k % mod * SIX % mod; return ret % mod; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;++i) scanf("%lld",&a[i]); Build(1,1,n); while (m--) { scanf("%d",&op); if (op == 1) scanf("%d%d",&x,&y), x ^= cnt, y ^= cnt, Change(1,1,n,x,y); else { scanf("%d%d%d",&x,&y,&z), x ^= cnt, y ^= cnt, z ^= cnt; flag = 1; LL minn = Query_min(1,1,n,x,y); LL sum = Get1(minn,y-x+1,z); if (sum != Query(1,1,n,x,y,1)) flag = 0; if (flag && Get2(minn,y-x+1,z) != Query(1,1,n,x,y,2)) flag = 0; if (flag) puts("Yes"), ++cnt; else puts("No"); } } return 0; }
1858: [Scoi2010]序列操作
维护各种操作,强行上线段树即可。
部分说明如下:
$l0/l1$维护该区段从左边开始最长的连续$0/1$
$r0/r1$维护该区段从右边开始最长的连续$0/1$
$sum0/sum1$维护该区段中$0/1$的个数
$mx1/mx0$维护该区段中最长连续$0/1$的个数
$num=\{-1,0,1\}$分别表示该区段数字不同/全为0/全为1
$rev$为翻转标志
对这些值进行维护即可。
#include <bits/stdc++.h> using namespace std; typedef long long LL; int read() { int x=0; bool f=0; char ch; for (ch=getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=1; for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; if (f) x=-x; return x; } const int NN = 100005; int n,m; struct TR { int l,r,l0,r0,l1,r1,mx0,mx1,sum0,sum1,num,rev,c; }tr[NN<<2]; void Rev(int k) { swap(tr[k].l0,tr[k].l1), swap(tr[k].r0,tr[k].r1), swap(tr[k].mx0,tr[k].mx1), swap(tr[k].sum0,tr[k].sum1); if (tr[k].num != -1) tr[k].num ^= 1; } void Color(int k,int v) { tr[k].rev = 0; int sum = tr[k].r - tr[k].l + 1; if (v == 0) { tr[k].sum0 = tr[k].l0 = tr[k].r0 = tr[k].mx0 = sum; tr[k].sum1 = tr[k].l1 = tr[k].r1 = tr[k].mx1 = 0; } else { tr[k].sum0 = tr[k].l0 = tr[k].r0 = tr[k].mx0 = 0; tr[k].sum1 = tr[k].l1 = tr[k].r1 = tr[k].mx1 = sum; } tr[k].num = v; } TR Merge(TR x,TR y) { TR tmp; tmp.l = x.l, tmp.r = y.r; tmp.rev = 0, tmp.c = -1; tmp.l0 = x.l0, tmp.l1 = x.l1, tmp.r0 = y.r0, tmp.r1 = y.r1; tmp.mx0 = max(x.mx0,y.mx0), tmp.mx1 = max(x.mx1,y.mx1); tmp.mx0 = max(tmp.mx0,x.r0+y.l0), tmp.mx1 = max(tmp.mx1,x.r1+y.l1); tmp.sum0 = x.sum0 + y.sum0, tmp.sum1 = x.sum1 + y.sum1; if (x.num == 0) tmp.l0 = x.mx0 + y.l0; else if (x.num == 1) tmp.l1 = x.mx1 + y.l1; if (y.num == 0) tmp.r0 = y.mx0 + x.r0; else if (y.num == 1) tmp.r1 = y.mx1 + x.r1; if (x.num == y.num) tmp.num = x.num; else tmp.num = -1; return tmp; } void push_up(int k) { tr[k] = Merge(tr[k<<1],tr[k<<1|1]); } void push_down(int k) { if (tr[k].l == tr[k].r) return; if (tr[k].c != -1) { tr[k<<1].c = tr[k<<1|1].c = tr[k].c; Color(k<<1,tr[k].c), Color(k<<1|1,tr[k].c), tr[k].c = -1; } if (tr[k].rev) { tr[k<<1].rev ^= 1, tr[k<<1|1].rev ^= 1; Rev(k<<1), Rev(k<<1|1), tr[k].rev = 0; } } void Build(int k,int l,int r) { tr[k].l = l, tr[k].r = r, tr[k].c = -1; if (l == r) { tr[k].num = read(); if (tr[k].num) tr[k].l1 = tr[k].r1 = tr[k].mx1 = tr[k].sum1 = 1; else tr[k].l0 = tr[k].r0 = tr[k].mx0 = tr[k].sum0 = 1; return; } int mid = (l+r) >> 1; Build(k<<1,l,mid), Build(k<<1|1,mid+1,r); push_up(k); } void Change(int k,int x,int y,int v) { push_down(k); int l=tr[k].l, r=tr[k].r; if (l == x && r == y) { Color(k,v), tr[k].c = v; return; } int mid = (l+r) >> 1; if (y <= mid) Change(k<<1,x,y,v); else if (x > mid) Change(k<<1|1,x,y,v); else Change(k<<1,x,mid,v), Change(k<<1|1,mid+1,y,v); push_up(k); } void Rever(int k,int x,int y) { push_down(k); int l = tr[k].l, r = tr[k].r; if (l == x && r == y) { Rev(k), tr[k].rev = 1; return; } int mid = (l+r) >> 1; if (y <= mid) Rever(k<<1,x,y); else if (x > mid) Rever(k<<1|1,x,y); else Rever(k<<1,x,mid), Rever(k<<1|1,mid+1,y); push_up(k); } TR Query(int k,int x,int y) { push_down(k); int l = tr[k].l, r = tr[k].r; if (l == x && r == y) return tr[k]; int mid = (l+r) >> 1; if (y <= mid) return Query(k<<1,x,y); else if (x > mid) return Query(k<<1|1,x,y); else return Merge(Query(k<<1,x,mid),Query(k<<1|1,mid+1,y)); } int Q_sum(int k,int x,int y) { push_down(k); int l = tr[k].l, r = tr[k].r; if (l == x && y == r) return tr[k].sum1; int mid = (l+r) >> 1; if (y <= mid) return Q_sum(k<<1,x,y); else if (x > mid) return Q_sum(k<<1|1,x,y); else return Q_sum(k<<1,x,mid)+Q_sum(k<<1|1,mid+1,y); } int main() { n = read(), m = read(); Build(1,1,n); int x,y,op; for (int i=1;i<=m;++i) { op = read(), x = read()+1, y = read()+1; switch (op) { case 0: Change(1,x,y,0); break; case 1: Change(1,x,y,1); break; case 2: Rever(1,x,y); break; case 3: printf("%d\n",Q_sum(1,x,y)); break; case 4: printf("%d\n",Query(1,x,y).mx1); break; } } return 0; }
2022年8月10日 13:01
Blue host Webmail lets the individual create their professional and personalized email address. Having a business or personal brand does require a personalized email address, which increases more credibility. The attraction from customers will be more when you use your business related or personal name in the mail instead of using @outlook or @gmail. Bluehost Webmail Login There are options under Blue host Webmail that allow users to create personal email without actually creating a website. The Blue host Webmail control panel allows you to create multiple emails with a user-friendly option to access the same.