T1
数列区间修改,单点查询。线段树,树状数组都可。(代码抄的)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 const int maxn=5e4+5; 7 8 int n,blo; 9 int v[maxn],bl[maxn],atag[maxn]; 10 11 void add(int a,int b,int c){ 12 for(int i=a;i<=min(bl[a]*blo,b);i++) 13 v[i]+=c; 14 if(bl[a]!=bl[b]) 15 for(int i=(bl[b]-1)*blo+1;i<=b;i++) 16 v[i]+=c; 17 for(int i=bl[a]+1;i<=bl[b]-1;i++) 18 atag[i]+=c; 19 } 20 21 int main() 22 { 23 scanf("%d",&n);blo=sqrt(n); 24 for(int i=1;i<=n;i++) scanf("%d",&v[i]); 25 for(int i=1;i<=n;i++) bl[i]=(i-1)/blo+1; 26 for(int i=1;i<=n;i++) 27 { 28 int op,a,b,c; 29 scanf("%d%d%d%d",&op,&a,&b,&c); 30 if(op==0) add(a,b,c); 31 if(op==1) printf("%d\n",v[b]+atag[bl[b]]); 32 } 33 return 0; 34 }
T2
统计区间比c*c小的个数
同样线段树也可以做,维护区间小于c*c的个数
分块的话,因为要找区间小于c*c的数,所以对于两个端点所在的block,每次修改后要重新排序,才能通过二分查找到小于c*c的个数。
复杂度:O(nlogn + n√nlog√n)
ps:这个题用分块的话换个姿势就T (╥﹏╥)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 const int maxn=5e4+5; 7 8 int n,blo; 9 int v[maxn],bl[maxn],atag[maxn]; 10 11 vector <int> V[505]; 12 13 inline int read() 14 { 15 char ch=getchar();int x=0,f=0; 16 while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar(); 17 while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); 18 return f?-x:x; 19 } 20 21 void reset(int x) 22 { 23 V[x].clear(); 24 for(int i=(x-1)*blo+1;i<=min(x*blo,n);i++) 25 V[x].push_back(v[i]); 26 sort(V[x].begin(),V[x].end()); 27 } 28 29 void add(int a,int b,int c){ 30 for(int i=a;i<=min(b,bl[a]*blo);i++) 31 v[i]+=c; 32 reset(bl[a]); 33 if(bl[a]!=bl[b]){ 34 for(int i=(bl[b]-1)*blo+1;i<=b;i++){ 35 v[i]+=c; 36 } 37 reset(bl[b]); 38 } 39 40 for(int i=bl[a]+1;i<=bl[b]-1;i++){ 41 atag[i]+=c; 42 } 43 } 44 45 46 int query(int a,int b,int c){ 47 int ans=0; 48 for(int i=a;i<=min(b,bl[a]*blo);i++) 49 if(v[i]+atag[bl[a]]<c*c) ans++; 50 if(bl[a]!=bl[b]) 51 for(int i=(bl[b]-1)*blo+1;i<=b;i++) 52 if(v[i]+atag[bl[b]]<c*c) ans++; 53 54 for(int i=bl[a]+1;i<=bl[b]-1;i++){ 55 int tmp=c*c-atag[i]; 56 ans+=lower_bound(V[i].begin(),V[i].end(),tmp)-V[i].begin(); 57 } 58 return ans; 59 } 60 61 62 63 int main() 64 { 65 n=read();blo=sqrt(n); 66 for(int i=1;i<=n;i++) v[i]=read(); 67 for(int i=1;i<=n;i++) {bl[i]=(i-1)/blo+1;V[bl[i]].push_back(v[i]);} 68 for(int i=1;i<=bl[n];i++) sort(V[i].begin(),V[i].end()); 69 for(int i=1;i<=n;i++) { 70 int op,a,b,c;op=read();a=read();b=read();c=read(); 71 if(op==0) add(a,b,c); 72 else printf("%d\n",query(a,b,c)); 73 } 74 return 0; 75 }
T3
这个题换个姿势就wa,真的变一变就wa。所以代码又是抄的(o(╥﹏╥)o),我好菜啊!
块内用set去重,找最大的值。
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 6 inline int read() 7 { 8 char ch=getchar();int x=0,f=0; 9 while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar(); 10 while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); 11 return f?-x:x; 12 } 13 14 int n,blo; 15 int v[maxn],bl[maxn],atag[maxn]; 16 set<int>st[105]; 17 18 void add(int a,int b,int c) 19 { 20 for(int i=a;i<=min(bl[a]*blo,b);i++) 21 { 22 st[bl[a]].erase(v[i]); 23 v[i]+=c; 24 st[bl[a]].insert(v[i]); 25 } 26 if(bl[a]!=bl[b]) 27 { 28 for(int i=(bl[b]-1)*blo+1;i<=b;i++) 29 { 30 st[bl[b]].erase(v[i]); 31 v[i]+=c; 32 st[bl[b]].insert(v[i]); 33 } 34 } 35 for(int i=bl[a]+1;i<=bl[b]-1;i++) 36 atag[i]+=c; 37 } 38 39 40 int query(int a,int b,int c) 41 { 42 int ans=-1; 43 for(int i=a;i<=min(bl[a]*blo,b);i++) 44 { 45 int val=v[i]+atag[bl[a]]; 46 if(val<c)ans=max(val,ans); 47 } 48 if(bl[a]!=bl[b]) 49 for(int i=(bl[b]-1)*blo+1;i<=b;i++) 50 { 51 int val=v[i]+atag[bl[b]]; 52 if(val<c)ans=max(val,ans); 53 } 54 for(int i=bl[a]+1;i<=bl[b]-1;i++) 55 { 56 int x=c-atag[i]; 57 set<int>::iterator it=st[i].lower_bound(x); 58 if(it==st[i].begin())continue; 59 --it; 60 ans=max(ans,*it+atag[i]); 61 } 62 return ans; 63 } 64 65 int main() 66 { 67 n=read();blo=1000; 68 for(int i=1;i<=n;i++)v[i]=read(); 69 for(int i=1;i<=n;i++) 70 { 71 bl[i]=(i-1)/blo+1; 72 st[bl[i]].insert(v[i]); 73 } 74 for(int i=1;i<=n;i++) 75 { 76 int f=read(),a=read(),b=read(),c=read(); 77 if(f==0)add(a,b,c); 78 if(f==1)printf("%d\n",query(a,b,c)); 79 } 80 return 0; 81 }
T4
简单区间修改取模。
分块竟然比线段树要快
线段树:


1 #include <bits/stdc++.h> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+5; 7 8 ll sum[maxn<<2]; 9 ll f[maxn<<2]; 10 11 ll read() 12 { 13 ll x=0,f=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 15 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 void pushdown(int rt,int m){ 20 if(f[rt]!=0){ 21 sum[rt<<1]+=(m-(m>>1))*f[rt]; 22 sum[rt<<1|1]+=(m>>1)*f[rt]; 23 f[rt<<1]+=f[rt];f[rt<<1|1]+=f[rt]; 24 f[rt]=0; 25 } 26 } 27 28 void build(int l,int r,int rt){ 29 if(l==r) 30 { 31 sum[rt]=read(); 32 f[rt]=0; 33 return ; 34 } 35 f[rt]=0; 36 int m=(l+r)>>1; 37 build(lson); 38 build(rson); 39 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 40 } 41 42 43 void update(int L,int R,int c,int l,int r,int rt){ 44 if(L<=l&&R>=r) 45 { 46 sum[rt]+=(r-l+1)*c; 47 f[rt]+=c; 48 return; 49 } 50 int m=(l+r)>>1; 51 pushdown(rt,r-l+1); 52 if(L<=m) update(L,R,c,lson); 53 if(R>m) update(L,R,c,rson); 54 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 55 } 56 57 58 ll query(int L,int R,int l,int r,int rt){ 59 if(L<=l&&R>=r) 60 { 61 return sum[rt]; 62 } 63 int m=(l+r)>>1; 64 pushdown(rt,r-l+1); 65 ll res=0; 66 if(L<=m) res+=query(L,R,lson); 67 if(R>m) res+=query(L,R,rson); 68 return res; 69 } 70 71 72 int main(){ 73 int n;n=read(); 74 build(1,n,1); 75 for(int i=1;i<=n;i++){ 76 int op,a,b,c; 77 op=read();a=read();b=read();c=read(); 78 if(op==0) update(a,b,c,1,n,1); 79 else if(op==1) printf("%lld\n",query(a,b,1,n,1)%(c+1)); 80 } 81 return 0; 82 }
分块:


1 #include <bits/stdc++.h> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+5; 7 8 ll read() 9 { 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 16 int n,blog; 17 ll v[maxn],bl[maxn],ata[maxn],sum[maxn]; 18 19 20 void add(int a,int b,int c){ 21 for(int i=a;i<=min((ll)b,bl[a]*blog);i++) 22 v[i]+=c,sum[bl[a]]+=c; 23 if(bl[a]!=bl[b]) 24 for(int i=(bl[b]-1)*blog+1;i<=b;i++) 25 v[i]+=c,sum[bl[b]]+=c; 26 for(int i=bl[a]+1;i<=bl[b]-1;i++) 27 ata[i]+=c; 28 } 29 30 ll query(int a,int b){ 31 ll ans=0; 32 for(int i=a;i<=min((ll)b,bl[a]*blog);i++) 33 ans+=v[i]+ata[bl[a]]; 34 if(bl[a]!=bl[b]) 35 for(int i=((bl[b]-1)*blog+1);i<=b;i++) 36 ans+=v[i]+ata[bl[b]]; 37 for(int i=bl[a]+1;i<=bl[b]-1;i++) 38 ans+=(ata[i]*blog)+sum[i]; 39 return ans; 40 } 41 42 int main(){ 43 n=read(); blog=sqrt(n); 44 for(int i=1;i<=n;i++) 45 { 46 v[i]=read(); 47 bl[i]=(i-1)/blog+1; 48 sum[bl[i]]+=v[i]; 49 } 50 cout <<endl; 51 for(int i=1;i<=n;i++){ 52 int op,a,b,c; 53 op=read();a=read();b=read();c=read(); 54 if(op==0) 55 add(a,b,c); 56 else if(op==1) printf("%lld\n",query(a,b)%(c+1)); 57 } 58 59 return 0; 60 }
分块还是写的磕磕绊绊,这么简单还是调了好长时间
T5
区间求和,修改为区间元素开方
之前用线段树做过一次,就是因为对于 a[i]<=2^31-1,最多开方次数为5次,之后就不会再变化,所以根据这个性质,对于还可以变化的整区间暴力修改。散区间也暴力修改


1 #include <bits/stdc++.h> 2 #define lson l,m,rt<<1 3 #define rson m+1,r,rt<<1|1 4 using namespace std; 5 typedef long long ll; 6 const int maxn=5e4+5; 7 8 ll read() 9 { 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 16 int n,blog; 17 ll v[maxn],bl[maxn],vis[maxn],sum[maxn]; 18 19 void add(int a,int b){ 20 for(int i=a;i<=min((ll)b,bl[a]*blog);i++){ 21 sum[bl[a]]-=v[i]; 22 v[i]=sqrt(v[i]); 23 sum[bl[a]]+=v[i]; 24 } 25 if(bl[a]!=bl[b]) 26 for(int i=(bl[b]-1)*blog+1;i<=b;i++){ 27 sum[bl[b]]-=v[i]; 28 v[i]=sqrt(v[i]); 29 sum[bl[b]]+=v[i]; 30 } 31 for(int i=bl[a]+1;i<=bl[b]-1;i++) 32 { 33 if(vis[i]==1) continue; 34 sum[i]=0; 35 vis[i]=1; 36 for(int j=(i-1)*blog+1;j<=i*blog;j++) 37 { 38 v[j]=sqrt(v[j]);sum[i]+=v[j]; 39 if(v[j]>1) vis[i]=0; 40 } 41 } 42 } 43 44 ll query(int a,int b){ 45 ll ans=0; 46 for(int i=a;i<=min((ll)b,bl[a]*blog);i++) 47 { 48 ans+=v[i]; 49 } 50 if(bl[a]!=bl[b]) 51 for(int i=((bl[b]-1)*blog+1);i<=b;i++) 52 { 53 ans+=v[i]; 54 } 55 for(int i=bl[a]+1;i<=bl[b]-1;i++) 56 { 57 ans+=sum[i]; 58 } 59 return ans; 60 } 61 62 int main(){ 63 n=read(); blog=sqrt(n); 64 for(int i=1;i<=n;i++) 65 { 66 v[i]=read(); 67 bl[i]=(i-1)/blog+1; 68 sum[bl[i]]+=v[i]; 69 } 70 for(int i=1;i<=n;i++){ 71 int op,a,b,c; 72 op=read();a=read();b=read();c=read(); 73 if(op==0) 74 add(a,b); 75 else if(op==1) printf("%lld\n",query(a,b)); 76 } 77 78 return 0; 79 }
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 int blo,n; 6 int v[maxn];int bl[maxn]; 7 8 vector <int> V[maxn]; 9 10 ll read() 11 { 12 ll x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 18 void ope(int a,int b){ 19 ll cnt=0;int x=1; 20 for(int i=1;i<=n;i++) 21 { 22 if(cnt+V[i].size()<a) cnt+=V[i].size(); 23 else 24 { 25 x=i; 26 break; 27 } 28 } 29 cnt=a-cnt; 30 vector <int> :: iterator it=V[x].begin(); 31 V[x].insert(it+cnt-1,b); 32 } 33 34 int query(int a){ 35 ll cnt=0;int x=1; 36 for(int i=1;i<=n;i++){ 37 if(cnt+V[i].size()<a) cnt+=V[i].size(); 38 else{ 39 x=i; 40 break; 41 } 42 } 43 cnt=a-cnt; 44 return V[x][cnt-1]; 45 } 46 47 int main(){ 48 n=read();blo=sqrt(n); 49 for(int i=1;i<=n;i++) 50 { 51 v[i]=read(); 52 bl[i]=(i-1)/blo+1; 53 V[bl[i]].push_back(v[i]); 54 } 55 56 for(int i=1;i<=n;i++) 57 { 58 int op,a,b,c; 59 op=read();a=read();b=read();c=read(); 60 if(op==0) ope(a,b); 61 else if(op==1) printf("%d\n",query(b)); 62 } 63 return 0; 64 }
没有想到其它做法,区间没有重构,水过