首页 > 代码库 > CF788E:New task
CF788E:New task
n个数字中,每个数有数字A和属性B,每次操作将某个点x的属性B改变为0或1,求满足这样要求的子序列的个数:
下标a<b<c<d<e,而Aa<=Ab=Ac=Ad>=Ae且Bb=Bc=Bd=1。
区间操作,首推线段树!(然后就不会了,跑去看别人的代码)
是这样的,重点在于中间那三个点,因为我们的修改操作只会影响修改的点的值的答案。
直接维护一个这样的子序列不太容易,所以多维护Aa<=Ab和Aa<=Ab=Ac和Ac=Ad>=Ae和Ad>=Ae的序列,然后线段树up的时候才可以左右合并答案。
大体思路就这样,由于线段树是要按照值来建的,也就是给每个值一棵线段树,为方便调值先离散化。
Aa<=Ab和Ad>=Ae即每个点左边<=它和右边<=它的数,可以用树状数组预处理,详见代码。
线段树中的信息用到“当前这棵子线段树的数的个数”size,以及上面提到的四个序列长度A,AB,BC,C,还有答案ABC。
在线段树叶子节点只算A,C和size,其他数组慢慢合并,详见代码中up。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 //#include<iostream> 7 using namespace std; 8 9 int n; 10 #define maxn 200011 11 struct BIT 12 { 13 int a[maxn]; 14 void clear() {memset(a,0,sizeof(a));} 15 int lowbit(int x) {return x&-x;} 16 void add(int x,int v) 17 { 18 for (;x<=n;x+=lowbit(x)) a[x]+=v; 19 } 20 int query(int x) 21 { 22 int ans=0; 23 for (;x;x-=lowbit(x)) ans+=a[x]; 24 return ans; 25 } 26 }bit; 27 const int mod=1000000007; 28 int Left[maxn],Right[maxn]; 29 #define maxs 2000011 30 struct segmenttree 31 { 32 struct Node 33 { 34 int size,A,C,AB,BC,ABC; 35 int son[2]; 36 }a[maxs]; 37 int size; 38 segmenttree() {size=0;} 39 void up(int x) 40 { 41 const int &p=a[x].son[0],&q=a[x].son[1]; 42 a[x].size=a[p].size+a[q].size; 43 a[x].A=(a[p].A+a[q].A)%mod; 44 a[x].C=(a[p].C+a[q].C)%mod; 45 a[x].AB=(a[p].AB+a[q].AB+a[p].A*1ll*a[q].size)%mod; 46 a[x].BC=(a[p].BC+a[q].BC+a[p].size*1ll*a[q].C)%mod; 47 a[x].ABC=(a[p].ABC+a[q].ABC+1ll*a[p].A*a[q].BC+1ll*a[p].AB*a[q].C)%mod; 48 } 49 void modify(int &x,int L,int R,int id,int v) 50 { 51 if (!x) x=++size; 52 if (L==R) 53 { 54 a[x].size=v*1; 55 a[x].A=v*Left[id]; 56 a[x].C=v*Right[id]; 57 a[x].AB=a[x].BC=a[x].ABC=0; 58 a[x].son[0]=a[x].son[1]=0; 59 } 60 else 61 { 62 const int mid=(L+R)>>1; 63 if (id<=mid) modify(a[x].son[0],L,mid,id,v); 64 else modify(a[x].son[1],mid+1,R,id,v); 65 up(x); 66 } 67 } 68 }seg; 69 struct Point 70 { 71 int v,id; 72 bool operator < (const Point &b) const {return v<b.v;} 73 }b[maxn]; 74 int a[maxn],cnt=0; 75 int root[maxn]; 76 int main() 77 { 78 scanf("%d",&n); 79 for (int i=1;i<=n;i++) scanf("%d",&b[b[i].id=i].v); 80 sort(b+1,b+1+n); 81 a[b[1].id]=cnt=1; 82 for (int i=2;i<=n;i++) 83 { 84 if (b[i].v!=b[i-1].v) cnt++; 85 a[b[i].id]=cnt; 86 } 87 memset(Left,0,sizeof(Left)); 88 memset(Right,0,sizeof(Right)); 89 bit.clear(); 90 for (int i=1;i<=n;i++) 91 { 92 Left[i]=bit.query(a[i]); 93 bit.add(a[i],1); 94 } 95 bit.clear(); 96 for (int i=n;i>=1;i--) 97 { 98 Right[i]=bit.query(a[i]); 99 bit.add(a[i],1); 100 } 101 int ans=0; 102 memset(root,0,sizeof(root)); 103 for (int i=1;i<=n;i++) 104 { 105 ans=(ans-seg.a[root[a[i]]].ABC+mod)%mod; 106 seg.modify(root[a[i]],1,n,i,1); 107 ans=(ans+seg.a[root[a[i]]].ABC)%mod; 108 } 109 int m,x,y; 110 scanf("%d",&m); 111 for (int i=1;i<=m;i++) 112 { 113 scanf("%d%d",&x,&y); 114 ans=(ans-seg.a[root[a[y]]].ABC+mod)%mod; 115 seg.modify(root[a[y]],1,n,y,x-1); 116 ans=(ans+seg.a[root[a[y]]].ABC)%mod; 117 printf("%d\n",ans); 118 } 119 return 0; 120 }
CF788E:New task
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。