随笔分类 -  树状数组

1
摘要:思路:树状数组统计。待验证,不知道是否对。#include#include#include#include#include#define lowbit(x) (x&(-x))#define Maxn 200010using namespace std;int C[Maxn],vi[Maxn],pre[Maxn],n,num[Maxn],ans[Maxn],ov[Maxn];struct Qu{ int l,r,i;}q[Maxn];int cmp(Qu a,Qu b){ return a.r<b.r;}void update(int pos,int val){ while(p.. 阅读全文
posted @ 2013-10-28 19:24 fangguo 阅读(222) 评论(0) 推荐(0)
摘要:思路:和求区间内有多少个不同的数一样,只不过改下权值。#include#include#include#include#include#define Maxn 50010#define LL __int64#define lowbit(x) (x&(-x))using namespace std;int pre[1000010],num[Maxn],n;LL ans[Maxn*4],C[Maxn];struct Query{ int i,l,r; int operatorm) break; } /* for(i=1;i<=n;i++) ... 阅读全文
posted @ 2013-10-09 16:32 fangguo 阅读(202) 评论(0) 推荐(0)
摘要:思路:二分查找位置,之后是裸的树状数组。#include#include#include#include#include#include#include#include#include#include#include#define pb push_back#define mp make_pair#define Maxn 100010#define Maxm 200010#define LL int#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x=val[i]-d) l--; if(sorted[r]>val[i]+d||r... 阅读全文
posted @ 2013-09-13 21:30 fangguo 阅读(147) 评论(0) 推荐(0)
摘要:思路:直接用long long 保存会WA。用下高精度加法就行了。#include#include#include#include#include#include#include#include#include#include#include#include#define pb push_back#define mp make_pair#define Maxn 50010#define Maxm 80002#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x=2;j--) update(nu... 阅读全文
posted @ 2013-09-04 15:06 fangguo 阅读(186) 评论(0) 推荐(0)
摘要:思路:简单树状数组#include#include#include#include#include#include#include#include#include#include#include#define pb push_back#define mp make_pair#define Maxn 120#define Maxm 80002#define LL __int64#define Abs(x) ((x)>0?(x):(-x))#define lson(x) (x<<1)#define rson(x) (x<<1|1)#define inf 0x7ffff 阅读全文
posted @ 2013-09-03 15:03 fangguo 阅读(192) 评论(0) 推荐(0)
摘要:思路:将查询区间按右节点的升序排列,然后插入第i个数的时候,若nun[i]+1已经插入,那么就update(pre[num[i]+1],-1);pre[]表示的是该数的位置。同样若num[i]-1存在就update(pre[num[i]-1],-1);因为他么与num[i]属于一组,故只需一个存在就行。当查询的右边界r等于i时,只需对其左边界求和就行,Sum(qt[j].l)。#include#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int C[Max 阅读全文
posted @ 2013-08-02 13:10 fangguo 阅读(176) 评论(0) 推荐(0)
摘要:思路:找出所有 a#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn],n;int Sum(int pos){ int sum=0; while(pos) { sum+=C[pos]; pos-=lowbit(pos); } return sum;}void update(int pos){ while(pos<=n) { C[pos]++; pos+... 阅读全文
posted @ 2013-08-01 16:42 fangguo 阅读(170) 评论(0) 推荐(0)
摘要:思路:定义一个map容器用来记录数ai上次出现的位置。将查询区间按右边界升序进行排序,当插入第i个数ai时,pre[ai]+1---->i的区间就会多一个不同的数,其值就是ai,那么可以用update(pre[ai]+1,ai)来保存,但又不能影响i之后的位置,故用update(i,-ai)来消除。每次对于右边界时i的查询区间,只要对其左边界求和就行了,即Sum(qt[i].l)。#include#include#include#include#include#define Maxn 40010#define lowbit(x) (x&(-x))using namespace s 阅读全文
posted @ 2013-08-01 13:47 fangguo 阅读(168) 评论(0) 推荐(0)
摘要:思路:这题的思路很容易想到,把所有时间点离散化,然后按时间一步一步来,当到达时间i的时候处理所有在i处的查询。这个代码怎一个挫字了得#include#include#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn*3],n,ans[Maxn];struct Flower{ int l,r;}flower[Maxn];struct Lisan{ int val,type,l; int pos; int operator q... 阅读全文
posted @ 2013-08-01 10:39 fangguo 阅读(228) 评论(0) 推荐(0)
摘要:思路:就是一个很普通的二维树状数组,注意的是x1,y1不一定在x2,y2的左下方。#include#include#include#include#define Maxn 1105#define lowbit(x) (x&(-x))using namespace std;int C[Maxn][Maxn],n=1010,LIST[Maxn][Maxn];int Sum(int i,int j){ int sum=0; int y; y=j; while(i) { j=y; while(j) { sum... 阅读全文
posted @ 2013-08-01 08:50 fangguo 阅读(207) 评论(0) 推荐(0)
摘要:思路:从一维扩展到三维。可以看看poj2155的解法。#include#include#include#include#define Maxn 102#define lowbit(x) (x&(-x))using namespace std;int C[Maxn][Maxn][Maxn],n;int Sum(int i,int j,int k){ int sum=0; int y,z; y=j,z=k; while(i) { j=y; while(j) { k=z; while(... 阅读全文
posted @ 2013-07-31 21:17 fangguo 阅读(137) 评论(0) 推荐(0)
摘要:思路:这题的处理方式和hdu4358有点像。我们用一个pre[x]表示约数x的倍数上次出现的位置,将查询按区间的右节点升序排序。num[i]的约数为j,如果pre[j]为0,就将pre[j]置为i;否则就update(pre[j],j),表示的意思是约数j肯定不是第一次出现,将pre[j]以前的区间更新最大约数。如果查询区间的右边界在i处,那么左边界在pre[j]以前就肯定就能取到j。因为num[pre[j]]和num[i]有一个公共约数j,且pre[j]和i被该查询区间所覆盖。#include#include#include#include#define Maxn 50010#define 阅读全文
posted @ 2013-07-31 17:59 fangguo 阅读(467) 评论(0) 推荐(1)
摘要:思路:从后面往前面插,用一个二维树状数组保存,c[i][0]表示比i小的元素和,c[i][1]表示比i小的元素个数。#include#include#include#include#define Maxn 100010#define lowbit(x) (x&(-x))using namespace std;__int64 C[Maxn][2],n,num[Maxn],cnt;__int64 Sum(__int64 pos){ __int64 sum=0; while(pos) { sum+=C[pos][0]; cnt+=C[pos][1]; ... 阅读全文
posted @ 2013-07-31 10:16 fangguo 阅读(175) 评论(0) 推荐(0)
摘要:思路:加一个数e就用update(e,1)。删除元素e就用update(e,-1)。找比a大的第k大的元素就用二分查找。#include#include#include#include#define Maxn 120010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn];int Sum(int pos){ int sum=0; while(pos) { sum+=C[pos]; pos-=lowbit(pos); } return sum;}void update(int... 阅读全文
posted @ 2013-07-31 09:23 fangguo 阅读(134) 评论(0) 推荐(0)
摘要:思路:我们只需坚守一个原则,本来就在左边的坚决不把它换到右边。也就是相邻的两个数,左边小,右边大,那么就不调换。这样对每个数,只要统计左边比它大的数的个数。可以从后面开始用树状数组统计比它小的数的个数是一样的。#include#include#include#include#define Maxn 1000010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn],num[Maxn],n,r[Maxn];void init(){ memset(C,0,sizeof(C));}int cmp(int a,int b){ r.. 阅读全文
posted @ 2013-07-30 20:52 fangguo 阅读(270) 评论(0) 推荐(0)
摘要:思路:从后面往前面统计,每次先sum+=Sum(num[i]+1),然后在update(num[i]+1,1)。这样每次Sum每次加的个数就是num[i]的逆序对个数。每次从队首调一个元素到队尾,逆序对的变化为sum=sum-num[i]+n-num[i]+1。减少的个数为num[i],增加的个数为n-num[i]-1。#include#include#include#include#define Maxn 5010#define lowbit(x) (x&(-x))using namespace std;int C[Maxn],num[Maxn],n;void init(){ mem 阅读全文
posted @ 2013-07-30 20:02 fangguo 阅读(159) 评论(0) 推荐(0)
摘要:这题对于O(n^2)的算法有很多,我这随便贴一个烂的,跑了375ms。#include#includeusing namespace std;int mat[8008];int main(){ int i,j,t,n; scanf("%d",&n); mat[0]=1; for(i=1;i=mat[i]) { mat[j]++;} } for(i=0;i#include#include#include#include#define Maxn 8010#define inf 0x7... 阅读全文
posted @ 2013-07-30 15:46 fangguo 阅读(206) 评论(0) 推荐(0)
摘要:对于网络流有一个定理:最小点权覆盖集=最大网络流;最大点权独立集=总权值-最小点权覆盖集;网络流解法代码如下:#include#include#include#include#define N 1010#define M 50010#define inf 1=n)return flow-lv; if(lv==0) break; } if(d[v]1) addedge(pos(i,j),pos(i-1,j),inf); if(j>1) ... 阅读全文
posted @ 2013-07-08 18:38 fangguo 阅读(264) 评论(0) 推荐(0)
摘要:题意:有N个节点,组成一棵树,1号节点是根节点。每个节点都有一个权值。现在有q个查询,每次查询根节点是U的子树中有多少个不同的权值恰好出现K次。思路:第一眼让人感觉是图论,但仔细分析发现单纯的搜索肯定会超时。这题分为另个部分:1.以u为根节点的子树有多少种不同的权值。2.权值为k的有多少。对于线性列表,查询一个区间有多少个不同的子节点,我们用一个pre[v]记录权值v上次出现的位置。那么当第i个数的权值为v时,区间pre[v]+1-->i这个区间就会多一个不同的数,那么可以用update(pre[v]+1,1)来更新。但是i之后的状态不能改变,故再用一个update(i+1,-1)。这样 阅读全文
posted @ 2013-05-24 12:50 fangguo 阅读(327) 评论(0) 推荐(0)
摘要:题意:美国有种防护盾,能抵挡恐怖分子的秘密武器,但每次抵挡后,需要t个单位时间去冷却,期间不能起抵挡作用。思路:我一开始用线段树做,但做到一半就坑爹了~~当修改了线段树的子节点信息时,父节点的左右节点就会产生不一致性,那么也就没法直接修改父节点。其实这题线段树和树状数组都能做。我们现在把问题分为两个部分:1.统计但会节点被攻击的次数;2.统计所有攻击中多少次无效;那么总的攻击次数减去无效的就是被攻击的次数了。关于统计被攻击的次数用线段树和树状数组都很好实现。多少次无效的,我们可以定义一个Atc[i][2]数组,记录第i次攻击的区间左右节点。用数组uint[i][0]表示i次攻击后,上次受攻击的 阅读全文
posted @ 2013-05-23 15:58 fangguo 阅读(221) 评论(0) 推荐(0)

1