Codeforces Round #225 (Div. 1) A:http://codeforces.com/problemset/problem/383/A
题意:给定一队牛,每只牛的头向左或向右,每个看向当前产奶牛的牛产奶量会减一判断怎么喂可以使减少的奶量最少。
题解:首先这样想,只考虑向左的时候,这时候肯定就是贪心啊,从最右边的开始,只考虑向右的时候,肯定是从最左边的开始,这样的贪心策略是正确的。但是这里有向左和向右的。所以就要考虑最左边的右边有多少个向左的,以及最右边向左的左边有多少个向右的,肯定选择数量少的那个,这样贪心是正确的,然后用两个树状数组维护一下,每次选取的时候,选一个最右边的0和最左边的1,然后比较0左边1的个数,和1右边0的个数,然后取小的那个,ans+=,这个过程可以用队列来维护。直到只剩下1或者零,那么,接下来就可以没有损耗了。注意要用long long ,手贱,没用,结果wa一发。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 const int N=2e5+10; 8 long long a[N]; 9 int n; 10 long long c[2][N]; 11 long long ans; 12 int lowbit(int x){ 13 return x&(-x); 14 } 15 void add(int flag,int x,long long val){ 16 while(x<=n){ 17 c[flag][x]+=val; 18 x+=lowbit(x); 19 } 20 } 21 long long getsum(int flag,int x){ 22 long long s=0; 23 while(x>0){ 24 s+=c[flag][x]; 25 x-=lowbit(x); 26 } 27 return s; 28 } 29 struct Node{ 30 int val; 31 int num; 32 }edge[N]; 33 void input(){ 34 memset(a,0,sizeof(a)); 35 scanf("%d",&n); 36 ans=0; 37 for(int i=1;i<=n;i++){ 38 scanf("%I64d",&a[i]); 39 if(a[i]==1) 40 add(1,i,1); 41 else 42 add(0,n-i+1,1); 43 } 44 for(int i=1;i<=n;i++){ 45 if(a[i]==0){ 46 edge[i].val=0; 47 edge[i].num=i; 48 } 49 else{ 50 edge[i].val=1; 51 edge[i].num=i; 52 } 53 } 54 } 55 int main(){ 56 input(); 57 queue<Node>Q0,Q1; 58 for(int i=n;i>=1;i--){ 59 if(edge[i].val==0) 60 Q0.push(edge[i]); 61 } 62 for(int i=1;i<=n;i++){ 63 if(edge[i].val==1) 64 Q1.push(edge[i]); 65 } 66 while((!Q1.empty())&&(!Q0.empty())){ 67 Node t1=Q1.front(); 68 Node t2=Q0.front(); 69 long long s1=getsum(0,n-t1.num+1); 70 long long s2=getsum(1,t2.num); 71 if(s1<=s2){ 72 ans+=s1; 73 Q1.pop(); 74 add(1,t1.num,-1); 75 } 76 else { 77 ans+=s2; 78 Q0.pop(); 79 add(0,n-t2.num+1,-1); 80 } 81 } 82 printf("%I64d ",ans); 83 }