首页 > 其他分享 >暑假集训随笔2 主席树/二维树状数组

暑假集训随笔2 主席树/二维树状数组

时间:2023-07-19 21:01:31浏览次数:43  
标签:数组 树状 int sum times 二维 暑假 集训 define

P4514 上帝造题的七分钟

题意

维护对二维平面上的矩形区域各元素进行加法以及对矩形区域求和
链接:https://www.luogu.com.cn/problem/P4514

思路

通过二维树状数组维护的二维前缀和利用差分实现矩形区域的区间加法与区间求和。
具体而言,二维的前缀和可以仿照一维的前缀和进行定义
一维的前缀和与差分数组的关系为

\[ \sum_{i=1}^{n}a[i]=sum[n]\qquad d[i]=a[i]-a[i-1] \]

相应地可以定义二维前缀和与差分

\[ \sum_{i=1}^{n}\sum_{j=1}^{m}a[i][j]=sum[n][m]\qquad d[n][m]=a[n][m]-a[n-1][m]-a[n][m-1]+a[n-1][m-1] \]

有了差分数组,我们可以仿照一维下的树状数组维护区间加减和求和的方式去维护二维情况。
对于一维下的情况,我们知道公式\(\sum_\limits{i=1}^{n}\sum_\limits{j=1}^{i}d[i]\)通过寻找\(d[i]\)被计算的次数
可以转化为\(\sum_\limits{i=1}^{n}(n-i+1)*d[i]\),于是可以通过多维护一个根据下表加权意义下的树状数组来解决这一计算问题。
对于二维情况,这一方法仍然适用。
image
通过以上例子我们可以得到对下方公式计算的启发.

\[\sum_{i=1}^x\sum_{j=1}^y\sum_{h=1}^i\sum_{k=1}^jd[h][k] \]

容易发现,第i行的元素在遍历到\([i,n]\)时才会被计算,
对于列也有类似的结论。故其可转化为

\[\sum_{i=1}^x\sum_{j=1}^yd[i][j]\times(x-i+1)\times(y-j+1) \]

\[=\begin{aligned}\sum_{i=1}^x\sum_{j=1}^yd[i][j]\times(xy+x+y+1)-d[i][j]\times i(y+1)-d[i][j]\times j(x+1)+d[i][j]\times i\times j\end{aligned} \]

其中x和y是定值,只需维护对应的四个树状数组即可。

代码

代码的细节不多,但是需要对二维树状数组有比较深刻的理解,比如我就在写update的时候搞错了更新要乘的i和j应该与循环变量相同还是和函数参数相同。实际上这个问题并不困难,因为我们本质上是单点修改因此数组各个位置的更新量自然应该是对应修改位置的定值。

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
#define dnt double
#define rep(i,j,k) for(int i=(j);i<=(k);++i)
#define dow(i,j,k) for(int i=(j);i>=(k);--i)
#define pr pair
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
inline int read(int &x) {
   x=0;int ff=1;char ch=getchar();
   while (ch<'0'||ch>'9') {
   	if (ch=='-') ff=-1;ch=getchar();
   }
   while (ch>='0'&&ch<='9') {
   	x=x*10+ch-48;ch=getchar();
   }
   return x*ff;
}
void write(int x) {
 if (x > 9)write(x / 10);
 putchar((x % 10) + '0');
}
inline int max(int a,int b) {return a>b?a:b;}
inline int min(int a,int b) {return a>b?b:a;}
inline int exgcd(int a,int b,int&x,int&y) {
   if(b==0) {x=1,y=0 ;return a ;} 
   else {int r=exgcd(b,a%b,x,y);int t=x ;x=y ;y=t-a/b*y ;return r ;}
}
const int N=2050;
int n,m;
int	f[N][N],fj[N][N],fi[N][N],fij[N][N];
int lowbit(int x){
   return x&(-x);
}
void update(int x,int y,int val){
   for(int i=x;i<=n;i+=lowbit(i)){
   	for(int j=y;j<=m;j+=lowbit(j)){
   		f[i][j]+=val;
   		fj[i][j]+=y*val;//j*val
   		fi[i][j]+=x*val;//
   		fij[i][j]+=x*y*val;//
   	}
   }
}
int query(int x,int y){
   int anss=0,anssi=0,anssj=0,anssij=0;
   for(int i=x;i>0;i-=lowbit(i)){
   	for(int j=y;j>0;j-=lowbit(j)){
   		anss+=f[i][j];
   		anssi+=fi[i][j];
   		anssj+=fj[i][j];
   		anssij+=fij[i][j]; 
   	}
   }
   return anss*(x*y+x+y+1)-anssi*(y+1)-anssj*(x+1)+anssij;
}
signed main() {
//	ios::sync_with_stdio(false),cin.tie(NULL);
   char s;int x1,y1,x2,y2,del;
   cin>>s>>n>>m;
   //cout<<n<<" "<<m<<endl;
   while((cin>>s)){
   //cout<<s<<endl;
   	if(s=='L'){
   		cin>>x2>>y2>>x1>>y1>>del;
   		update(x1+1,y1+1,del);
   		update(x2,y2,del);
   		update(x1+1,y2,-del);
   		update(x2,y1+1,-del);	
   	}
   	else{
   		cin>>x2>>y2>>x1>>y1;
   		cout<<query(x1,y1)-query(x2-1,y1)-query(x1,y2-1)+query(x2-1,y2-1)<<endl;
   	}
   }
   
   return 0;
}

标签:数组,树状,int,sum,times,二维,暑假,集训,define
From: https://www.cnblogs.com/WXk-k/p/17565822.html

相关文章

  • 20230719巴蜀暑期集训测试总结
    T1赛时打了一个\(O(n^3)\)\(16pts\)暴力和一个似乎可以过一个\(20pts\)特殊性质但其余无正确性的贪心。结果出来发现特殊性质挂了一个点,另一个地方还莫名其妙对了。说明特殊性质挂掉了,如果运气不好可能就挂到\(16pts\)了。考后看题解发现\(O(n^2)\)其实也是不难想的,有点......
  • 暑假周记(7.18)
    唉,昨天又忘写了,被小孩们调皮捣蛋气的,中午买饭还跟路边一个车(车主开门不看环境,直接就开,我没反应过来,直接撞到人家车门上了,疼的我差点饭吃不下去,浑身冒冷汗,得亏我骑得不快)碰了,郁闷的一上午,下午教那个小升初的,数学咋教也不会,哎。......
  • 集训游记 7.19-7.20 图论
    最小生成树MSTP5994[PA2014]Kuglarz考虑连边\(i,j\)表示花费代价知道区间\([i,j)\)的奇偶性.容易发现\(i,j\)联通就可以发现表示出\([i,j)\).考虑最终局面,一定要推出每个\([i,i+1)\)的奇偶性.要求每对\([i,i+1)\)联通.即整张图联通.最小生成树k条白边最小生成树......
  • 20230718巴蜀暑期集训测试总结
    T1做了\(3h\),时间复杂度不对,小样例都还有一个没过。考虑容斥,不连通的情况枚举\(1\)号点所在连通块。设\(f_{S,i}\)表示\(S\)连通且选了\(i\)条边的方案数。设\(inb_s\)表示\(S\)内部的边数。那么有转移:\[f_{S,i}=\binom{inb_S}i-\sum_{T\subsetneqqS,1\inT}......
  • hdu 2227 Find the nondecreasing subsequences (树状数组+dp+离散化)
    题意:给定一个长度为n(n<=100000)的整数序列,求其中的递增序列的个数。对于某些序列中的递增序列的个数是可以用dp来求解的,其状态转移方程为:dp[i]=sum(dp[j])+1,j<i&&a[j]<a[i]根据状态转移方程可以得知这样dp的时间复杂度为O(n^2),而对于题目给定的10^6的数量级来说,这样......
  • 暑假第三周
    [湖湘杯2018]Replace先脱壳直接定位到加密函数提取byte_40150,byte_402151和byte_4021A0数据,照着写解密脚本,直接爆破expdata=[0x32,0x61,0x34,0x39,0x66,0x36,0x39,0x63,0x33,0x38,0x33,0x39,0x35,0x63,0x64,0x65,0x39,0x36,0x64,0x36,0x64......
  • 暑假周记(7.17)
    周一三年级的小孩一如既往的听话,四年级的小孩一如既往的让我心烦下午给小孩上完课,去剪头发,然后就被另一个补课的老师(大姨)请吃饭,这个大姨的闺女是北大学语文的,见到真人根本没有想象中的北大高材生的样子,不问学历,你就会以为她是个普通的大学生。......
  • 2023ACM暑期集训 DAY 3
    目前进度——动态规划1:线性dp、背包问题,区间好题1012[NOIP1999]拦截导弹前言本题不重要,重要的是关于伪单调栈求最长单调子序列的理解。伪单调栈求最长单调子序列的一些理解重点最终伪单调栈中的序列不一定是最长单调子序列。以最长上升子序列为例,解释操作的意图。若目前......
  • 【暑假题目】20230712 帧处理
    帧处理题目在物联网应用中需要经常处理数据帧,请你写一段处理数据帧的代码将收到的数据进行解析输出提示:1、数据帧的长度不定,但是帧头帧尾是固定的2、数据帧的参数数量不定,请注意3、每次收到的数据可能不是完整的一帧,但是不能把不完整的数据帧丢弃,应该等待到下一完整帧接收到后才......
  • 你省(福建)省队集训模拟赛题解
    Day5$\texttt{T1}$简要题意有两个正整数\(a<b\le10^9\),给出\(\dfrac{a}{b}\)的小数点后\(19\)位,要求还原\(a,b\),保证有解。solution一个科技:\(\texttt{Stern-Brocottree}(SBT)\),可以参考这个博客学习。先给出$O(n)$找的代码#include<bits/stdc++.h>#defineLL......