1.(1005E2)http://codeforces.com/contest/1005/problem/E2
题意:给定一个长度为n的排列,先求有多少个区间[l,r]满足该区间的中位数为m
分析:设置函数count(m):表示对于给定长度为n的序列,有多少个区间的中位数是>=m的(当【区间>=m数的个数】>【区间<m的个数】时满足).最终的答案为count(m)-count(m+1)。
那么如何求解count(m)?设置变量cnt表示当前累计的值,初始值为n,当a[i]>=m时,cnt++;当a[i]<m时,cnt--。从头开始枚举区间的右端点[1,i],并计算cnt(1,i),每次只需要找出前面有多少个j满足cnt(1,j)<cnt(1,i)即可。设置sum[x]表示cnt=x的个数有多少。
那么如何求解前面有多少个数小于cnt(1,i)呢?设置变量add,表示满足cnt(1,j)<cnt(1,i-1)的数有多少。每次枚举第i位时,若a[i]>=m,则先add+=sum[cnt],cnt++。否则cnt--,add-=sum[cnt](有点类似于莫队算法中一步步更新)。每次访问一个i时,最后的答案result+=add。
参考:http://www.cnblogs.com/widsom/p/9290269.html
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 typedef long long ll; 6 const int maxn=2e5+10; 7 int a[maxn],sum[2*maxn],n; 8 9 ll count(int m) 10 { 11 memset(sum,0,sizeof(sum)); 12 int cnt=n; 13 sum[n]=1; 14 ll add=0,result=0; 15 for ( int i=1;i<=n;i++ ) 16 { 17 if ( a[i]>=m ) 18 { 19 add+=sum[cnt]; 20 cnt++; 21 } 22 else 23 { 24 cnt--; 25 add-=sum[cnt]; 26 } 27 sum[cnt]++; 28 result+=add; 29 } 30 return result; 31 } 32 33 int main() 34 { 35 int m,i,j,k,x,y,z; 36 ll ans; 37 while ( scanf("%d%d",&n,&m)!=EOF ) 38 { 39 for ( i=1;i<=n;i++ ) scanf("%d",&a[i]); 40 ans=count(m)-count(m+1); 41 printf("%lld\n",ans); 42 } 43 return 0; 44 }
1005E2
2.(1005F)http://codeforces.com/contest/1005/problem/F
题意:有n个点和m条无向边,求至多k种挑选n-1边的方案,满足根(编号为1的点)到所有点的距离之和最小,输出方案个数
分析:设置b[i]表示点i到根的最短距离(通过bfs)实现。然后对于一个点u来说考虑所有的边(u,v),若满足d[u]==d[v]+1,那么该边最终是可以选择的,设置G[u]表示u点的前驱的边中有哪些是可以选择的。设置f[i]表示对于点i当前选择第G[i][f[i]]条边,所有的f[i]初始化为0。所有对于编号为[2,n],每次挑选前驱中的一条边,最后组成的无向图是一定满足条件的。
那么如何挑选出k种方案呢?思路大致同数字中的进位(个位满10,十位加1;十位满10,百位+1。以此类推),此处也一样,f[i]==G[i].size(),f[i]==0,f[i+1]++.直到最后不能加为止
参考:http://codeforces.com/blog/entry/60511
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #include<queue> 6 #include<string> 7 #include<iostream> 8 using namespace std; 9 const int maxn=2e5+10; 10 const int inf=1e9; 11 vector<int>E[maxn],G[maxn]; 12 vector<string>ans; 13 int a[maxn],b[maxn],f[maxn],d[maxn],n; 14 15 void BFS() 16 { 17 for ( int i=1;i<=n;i++ ) d[i]=inf; 18 d[1]=0; 19 queue<int>que; 20 que.push(1); 21 while ( !que.empty() ) 22 { 23 int u=que.front(); 24 que.pop(); 25 for ( int i=0;i<E[u].size();i++ ) 26 { 27 int v=E[u][i]; 28 if ( d[v]==inf ) 29 { 30 d[v]=d[u]+1; 31 que.push(v); 32 } 33 } 34 } 35 } 36 37 int main() 38 { 39 int m,k,i,j,x,y,z,u,v,cnt; 40 while ( scanf("%d%d%d",&n,&m,&k)!=EOF ) 41 { 42 ans.clear(); 43 for ( i=1;i<=n;i++ ) 44 { 45 E[i].clear(); 46 G[i].clear(); 47 } 48 for ( i=1;i<=m;i++ ) 49 { 50 scanf("%d%d",&a[i],&b[i]); 51 E[a[i]].push_back(b[i]); 52 E[b[i]].push_back(a[i]); 53 } 54 BFS(); 55 for ( i=1;i<=m;i++ ) 56 { 57 u=a[i],v=b[i]; 58 if ( d[u]==d[v]+1 ) G[u].push_back(i); 59 if ( d[v]==d[u]+1 ) G[v].push_back(i); 60 } 61 memset(f,0,sizeof(f)); 62 cnt=0; 63 for ( j=1;j<=k;j++ ) 64 { 65 string s(m,‘0‘); 66 for ( i=2;i<=n;i++ ) 67 { 68 s[G[i][f[i]]-1]=‘1‘; 69 } 70 ans.push_back(s); 71 bool ok=false; 72 for ( i=2;i<=n;i++ ) 73 { 74 if ( f[i]+1<G[i].size() ) 75 { 76 ok=true; 77 f[i]++; 78 break; 79 } 80 else f[i]=0; 81 } 82 if ( !ok ) break; 83 } 84 cout<<ans.size()<<endl; 85 for ( i=0;i<ans.size();i++ ) cout<<ans[i]<<endl; 86 } 87 return 0; 88 }
1005F
原文地址:https://www.cnblogs.com/HDUjackyan/p/9293613.html