1.不可做题。
求出满足
$$\sum_{i=1}^{m}{x_i}\leq s$$
对任意$$i\leq m,x_i>0$$
对所有$$i,x_i\leq t$$
的解数
答案对10^9+7取模
m-n<=1000,t<=100000,m<=1E9,nt<=s<=1E18
2.树上LIS:一棵树,点权是一个排列。选出最多的点,使得每一个被选中的点,子树中没有比这个点权更大的点。
对于每个点,维护当前答案集合。这个集合的意义是,将元素从小到大排序,第i个元素的值表示能够选出恰好i的点的最小权值是多少。每次转移时,尝试将比当前值更大且最小的值删去,并加入集合中,可见这就是一个启发式合并。虽然无法知道具体的方案,但能算出个数。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=2E5+5; 4 int n,tot,ans,val[maxn]; 5 int size,head[maxn]; 6 multiset<int>S[maxn]; 7 struct edge 8 { 9 int to,next; 10 }E[maxn*2]; 11 inline void add(int u,int v) 12 { 13 E[++size].to=v; 14 E[size].next=head[u]; 15 head[u]=size; 16 } 17 void dfs(int u) 18 { 19 for(int i=head[u];i;i=E[i].next) 20 { 21 int v=E[i].to; 22 dfs(v); 23 if(S[u].size()>S[v].size()) 24 swap(S[u],S[v]); 25 for(multiset<int>::iterator pt=S[v].begin();pt!=S[v].end();++pt) 26 S[u].insert(*pt); 27 } 28 multiset<int>::iterator pt=S[u].lower_bound(val[u]); 29 if(pt!=S[u].end()) 30 S[u].erase(pt); 31 S[u].insert(val[u]); 32 } 33 int main() 34 { 35 freopen("tree.in","r",stdin); 36 freopen("tree.out","w",stdout); 37 ios::sync_with_stdio(false); 38 cin>>n; 39 for(int i=1;i<=n;++i) 40 { 41 int x,y; 42 cin>>x>>y; 43 val[i]=x; 44 if(y!=0) 45 add(y,i); 46 } 47 dfs(1); 48 cout<<S[1].size()<<endl; 49 return 0; 50 }
3.有三个n排列a,b,c,求出有多少合法的三元组。合法的定义为,存在一个下标集合,使得$(x,y,z)=(max_{i∈S}a_i,max_{i∈S}b_i,max_{i∈S}c_i)$。
可以发现,有很多无用的下标集合。我们现在只考虑所有合法三元组的“最小表示”,即它的下标集合中没有冗余的信息。可以证明,两者是一一对应的。
对于所有可能的情况,下标集合的大小为1或2或3。若大小为1,贡献为n。若大小为2,表明这个集合的两个位置上存在两种最大值。若大小为3,则三个位置上有三种最大值。
对于大小为2的下标集合,考虑容斥。不合法的集合的个数,即为一个位置上所有数字都对应大于另一个位置的集合的个数,这显然是一个三位偏序问题。
对于大小为3的下标集合,考虑容斥。方便起见,记(x,y,z)表示三个位置上分别有x,y,z种最大值(不考虑顺序)。(3,0,0)显然也是个三位偏序。要统计(2,1,0),我们假设2的位置上存在一个a排列中的最大值。我们先对a排序,对于b排列,统计前面有多少数字大于当前位置的b排列上的数字。算完后(对a,b,c排列都算了一遍),统计了3次(3,0,0),3次(2,1,0),(3,0,0)可以由前面的结果减去,就得到了(2,1,0)的个数
复杂度nlog^2n。
1 #pragma GCC optimize 2 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long int ll; 5 const int maxn=2E5+5; 6 ll n,tot,ans[maxn]; 7 int A[maxn],B[maxn],C[maxn]; 8 int where[maxn],tmp[maxn]; 9 struct pt 10 { 11 int a,b,c; 12 }a[maxn]; 13 inline bool cmpA(const pt&A,const pt&B) 14 { 15 return A.a<B.a; 16 } 17 inline bool cmpB(const pt&A,const pt&B) 18 { 19 return A.b<B.b; 20 } 21 struct BIT 22 { 23 ll t[maxn]; 24 inline int lowbit(int x) 25 { 26 return x&(-x); 27 }; 28 inline void add(int x,ll y) 29 { 30 while(x<=n) 31 { 32 t[x]+=y; 33 x+=lowbit(x); 34 } 35 } 36 inline void set(int x,int y) 37 { 38 while(x<=n) 39 { 40 t[x]=y; 41 x+=lowbit(x); 42 } 43 } 44 inline ll ask(int x) 45 { 46 ll sum=0; 47 while(x) 48 { 49 sum+=t[x]; 50 x-=lowbit(x); 51 } 52 return sum; 53 } 54 inline void clear() 55 { 56 memset(t,0,sizeof(t)); 57 } 58 }T; 59 void cdq(int l,int r) 60 { 61 if(l==r) 62 return; 63 int mid=(l+r)>>1; 64 cdq(l,mid),cdq(mid+1,r); 65 int i=l,j=mid+1,k=l; 66 while(k<=r) 67 { 68 if(j>r||(i<=mid&&a[where[i]].b<a[where[j]].b)) 69 { 70 T.add(a[where[i]].c,1); 71 tmp[k++]=where[i++]; 72 } 73 else 74 { 75 ll x=T.ask(a[where[j]].c); 76 ans[where[j]]+=x; 77 tmp[k++]=where[j++]; 78 } 79 } 80 for(int i=l;i<=mid;++i) 81 T.set(a[where[i]].c,0); 82 for(int i=l;i<=r;++i) 83 where[i]=tmp[i]; 84 } 85 inline ll get1() 86 { 87 return n; 88 } 89 inline bool check(pt a,int x,int y,int z) 90 { 91 return a.a==x||a.b==y||a.c==z; 92 } 93 inline ll get2() 94 { 95 ll sum=n*(n-1)/2; 96 for(int i=1;i<=n;++i) 97 sum-=ans[i]; 98 return sum; 99 } 100 inline ll get3() 101 { 102 ll sum=n*(n-1)*(n-2)/6; 103 sort(a+1,a+n+1,cmpA); 104 T.clear(); 105 for(int i=1;i<=n;++i) 106 { 107 ll x=T.ask(a[i].b-1); 108 sum-=x*(x-1)/2; 109 T.add(a[i].b,1); 110 } 111 T.clear(); 112 for(int i=1;i<=n;++i) 113 { 114 ll x=T.ask(a[i].c-1); 115 sum-=x*(x-1)/2; 116 T.add(a[i].c,1); 117 } 118 sort(a+1,a+n+1,cmpB); 119 T.clear(); 120 for(int i=1;i<=n;++i) 121 { 122 ll x=T.ask(a[i].c-1); 123 sum-=x*(x-1)/2; 124 T.add(a[i].c,1); 125 } 126 for(int i=1;i<=n;++i) 127 sum+=ans[i]*(ans[i]-1); 128 return sum; 129 } 130 inline void solve() 131 { 132 for(int i=1;i<=n;++i) 133 a[i]=(pt){A[i],B[i],C[i]},where[i]=i; 134 sort(a+1,a+n+1,cmpA); 135 cdq(1,n); 136 cout<<get1()+get2()+get3()<<endl; 137 } 138 int main() 139 { 140 freopen("subset.in","r",stdin); 141 freopen("subset.out","w",stdout); 142 ios::sync_with_stdio(false); 143 cin>>n; 144 for(int i=1;i<=n;++i) 145 cin>>A[i]; 146 for(int i=1;i<=n;++i) 147 cin>>B[i]; 148 for(int i=1;i<=n;++i) 149 cin>>C[i]; 150 solve(); 151 return 0; 152 }