题目意思是给定序列长度同为n的数列a,b;
要求出所有的子集元素的 2 ^ (max(a) ) * 3 ^ (max(b))的和。
分析:
首先对只有一个数组a,我们的通常思路是先排序 , 递推算法求解。 ans[ i ] = ans[ i-1 ] + 2^(i-1) * 2^a[ i ];
那么多了一个b数组,可以先按b排序 。
记走到 i , 前面 a的值比ai小的有x个, 比 ai 大的 位置为 p1 , p2 , ... pk.
那么 走到i,只需统计 i 必选的和。
ans[ i ] = ans[ i-1 ] + (2^x * 2^ai + 2^x*2^ap1 + 2^(x+1)*2^ap2 + .... + 2^(x+k-1)*2^apk) * 3^bi;
这样先给每个a[ i ] 一个rank(ai越小rank越小) ,加入线段树,维护2^(x)*2^ai, 其中x代表走到i时,比ai小的aj 有几个。
#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <map> #define ls rt<<1 #define rs rt<<1|1 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; #define rep(i,n) for(int i=0;i<(int) n; i++) #define rep1(i,x,y) for(int i=x;i<=(int)y; i++) const int maxn = 1e5 + 100; const ll mod = 1e9 + 7; struct node{ ll sum, cnt; }a[maxn<<2]; int n; ll col[maxn<<2]; ll pow_(int nn,int b){ ll ans = 1 , te = nn; while(b){ if(b&1) ans=ans*te%mod; b>>=1; te=te*te%mod; } return ans; } void push_up(int rt){ a[rt].cnt = a[ls].cnt+a[rs].cnt; a[rt].sum = (a[ls].sum+a[rs].sum)%mod; } void push_down(int rt){ if(col[rt] > 1){ col[ls] = (col[ls]*col[rt])%mod; col[rs] = (col[rs]*col[rt])%mod; a[ls].sum = a[ls].sum*col[rt]%mod; a[rs].sum = a[rs].sum*col[rt]%mod; col[rt] = 1; } } void build(int l,int r,int rt){ a[rt].sum = a[rt].cnt = 0; col[rt] = 1; if(l == r) return ; int m=(l+r)>>1; build(lson); build(rson); } void mul(int l,int r,int rt,int L,int R){ if(L<=l&&r<=R){ a[rt].sum = a[rt].sum*2%mod; col[rt]=col[rt]*2%mod; return ; } push_down(rt); int m=(l+r)>>1; if(L<=m) mul(lson,L,R); if(R> m) mul(rson,L,R); push_up(rt); } int query_cnt(int l,int r,int rt,int L,int R){ if(L<=l&&r<=R) return a[rt].cnt; push_down(rt); int m=(l+r)>>1 , all = 0; if(L<=m) all += query_cnt(lson,L,R); if(R> m) all += query_cnt(rson,L,R); return all; } ll query_sum(int l,int r,int rt,int L,int R){ if(L<=l&&r<=R) return a[rt].sum; push_down(rt); int m=(l+r)>>1 ; ll all = 0; if(L<=m) all += query_sum(lson,L,R); if(R> m) all = (all+query_sum(rson,L,R))%mod; return all; } void update(int l,int r,int rt,int p,int aa){ if(l==r){ a[rt].cnt = 1; ll x = (l==1 ? 0 : query_cnt(1,n,1,1,l-1)); a[rt].sum = pow_(2,x+aa); return ; } push_down(rt); int m=(l+r)>>1; if(p <= m) update(lson,p,aa); if(p > m) update(rson,p,aa); push_up(rt); } struct node2{ int a,b,id; }st[maxn]; int cmp1(node2 A, node2 B){ return A.a < B.a;} map<int,int> Rank; int cmp2(node2 A, node2 B){ return A.b < B.b; } int main() { while(scanf("%d",&n)==1){ build(1,n,1); rep1(i,1,n) scanf("%d %d",&st[i].a,&st[i].b),st[i].id = i; sort(st+1,st+1+n,cmp1); Rank.clear(); rep1(i,1,n) Rank[st[i].id] = i ; sort(st+1,st+1+n,cmp2); ll ans = 0; rep1(i,1,n){ update(1,n,1,Rank[st[i].id],st[i].a); ans = (ans + query_sum(1,n,1,Rank[st[i].id],n)*pow_(3,st[i].b)%mod)%mod; if(Rank[st[i].id]+1 <= n) mul(1,n,1,Rank[st[i].id]+1,n); } printf("%I64d\n",ans); } return 0; }