zoukankan      html  css  js  c++  java
  • usaco 奶牛集会 && 奶牛抗议

    奶牛集会

    Description

    约翰家的N头奶牛每年都会参加“哞哞大会” 。哞哞大会是世界奶牛界的盛事。集会上 的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等。当然,哞哞大叫肯定也包括在内。 奶牛们的叫声很大,很多奶牛在参加多年活动之后,实际上已经失去了一部分的听力。

    奶牛们已经站在了一条直线上,i号奶牛的坐标为Xi,她只能听到大于Vi的声音。每头奶 牛的位置坐标都是唯一的。

    如果i号和j号奶牛想对话,则他们使用的音量为max {Vi, Vj} × |Xi −Xj|

    N头奶牛可以组合成N(N − 1)/2对奶牛,假设每对奶牛都使用最小的音量在对话,请计 算所有奶牛产生的总音量是多少。

    Input Format

    第一行:单个整数:N,1 ≤ N ≤ 20000

    第二行到第N + 1行:每行有两个用空格分开的整数,Vi和Xi,1 ≤ Vi ≤ 20000, 1 ≤ Xi ≤ 20000

    Output Format

    第一行:单个整数,表示最小音量之和

    ----------------------------------------------------------

    正解=线段树(其实用树状数组也可以)

    注意到max{vi,vj}中,显然只有大的才有贡献

    将 vi 从小到大排序一一进树:

        设当前做到 i  

        先统计当前线段树中比xi大的个数num1及和sum1,ans+=vi*(sum1-num1*xi)

        再统计当前线段树中比xi小的个数num2及和sum2,ans+=vi*(num2*xi-sum2)

        将 xi 插入线段树

    Ps.好像很都存在两个相对大小变量的题,按其中一个变量排序后,题目都会变得很愉悦~

    代码如下:

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<string>
     5 #include<iostream>
     6 #define INF 9999999
     7 #define LL long long
     8 using namespace std;
     9 struct Point{
    10     int x;
    11     long long v;
    12 }a[20001];
    13 bool cmp(const Point&X,const Point&Y){
    14     return X.v<Y.v;
    15 }
    16 int Min=INF,Max=-INF;
    17 int L,R,o,n;
    18 long long sum[200000],num[200000];
    19 long long now,ans;
    20 long long query(int root,int l,int r){
    21     if(!num[root]) return 0;
    22     if(L<=l&&r<=R) 
    23       return  sum[root]-num[root]*now;
    24     int mid=(l+r)>>1;
    25     long long t=0;
    26     if(mid>=L) t+=query(root<<1  ,l  ,mid);
    27     if(mid<R)  t+=query(root<<1|1,mid+1,r);
    28     return t;
    29 }
    30 void insert(int root,int l,int r,int p){
    31     sum[root]+=p;
    32     num[root]++;
    33     if(l==r)  return ;
    34     int mid=(l+r)>>1;
    35     if(mid>=p) insert(root<<1,l,mid,p);
    36     else insert(root<<1|1,mid+1,r,p);
    37 }
    38 int main(){
    39     scanf("%d",&n);
    40     for(int i=1;i<=n;i++){
    41       scanf("%lld%d",&a[i].v,&a[i].x);
    42       Min=min(a[i].x,Min);
    43       Max=max(a[i].x,Max);
    44     }
    45     sort(a+1,a+1+n,cmp);
    46     LL T=0;
    47     for(int i=1;i<=n;i++){
    48         now=a[i].x;
    49         L=a[i].x ; R=Max;
    50         ans+=a[i].v*query(1,Min,Max);
    51         L=Min ;      R=a[i].x;
    52         ans-=a[i].v*query(1,Min,Max);
    53         insert(1,Min,Max,a[i].x);
    54     }
    55     printf("%lld",ans);
    56 }
    View Code

     -----------------------------------------------------------------------------------

    奶牛抗议 

    Description

    约翰家的N头奶牛聚集在一起,排成一列,正在进行一项抗议活动。第i头奶牛的理智度 为Ai,Ai可能是负数。约翰希望奶牛在抗议时保持理性,为此,他打算将所有的奶牛隔离成 若干个小组,每个小组内的奶牛的理智度总和都要大于零。由于奶牛是按直线排列的,所以 一个小组内的奶牛位置必须是连续的。

    请帮助约翰计算一下,存在多少种不同的分组的方案。由于答案可能很大,只要输出答 案除以1,000,000,009的余数即可。

    Input Format

    第一行:单个整数:N,1 ≤ N ≤ 10^6

    第二行到N + 1行:在第i + 1行有一个整数:Ai,表示第i头奶牛的理智度,−10^5 ≤ Ai ≤ 10^5

    Output Format

    第一行:单个整数,表示分组方案数除以1,000,000,009的余数

    --------------------------------------------------------------------------------------------------

    正解=离散化+树状数组,

    和上一题有异曲同工之妙~

    设f[i] 为到第 i 只奶牛有几种分组,

    设sum[i]为奶牛的前缀和

    显然 f[i]= ∑f[j](sum[i]-sum[j]>=0)

    注意到条件可以转化为 sum[i]>=sum[j],

    f[i]=在 i 前 sum[j] 小于 sum[j] 的 f[i] 的和

    可以用树状数组求和(由于只有单点修改,用树状数组比较方便 >_<)

    sum中显然有许多无用间隔,离散之,

    代码如下:

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<string>
     5 #include<cmath>
     6 #include<queue>
     7 #include<iostream>
     8 #define INF 999999999999
     9 #define LL long long
    10 #define N 1000002
    11 #define key 1000000009
    12 //using namespace std ;
    13 struct Cow{
    14     LL sum;
    15     int p;
    16 }a[N];
    17 bool cmp(const Cow &x,const Cow &y){
    18     return x.sum<y.sum;
    19 }
    20 int L,R,P,n,p[N];
    21 LL sum[N];
    22 int lowbit(int x){
    23     return x&(-x);
    24 }
    25 void update(int x,LL val){
    26     while(x<=n){
    27         sum[x]=(sum[x]+val)%key;
    28         x+=lowbit(x);
    29     }
    30 }
    31 LL cal(int x){
    32     LL temp=0;
    33     while(x){
    34         temp=(temp+sum[x])%key;
    35         x-=lowbit(x);
    36     }
    37     return temp;
    38 }
    39 int main(){
    40     scanf("%d",&n);
    41     for(int i=1;i<=n;i++){
    42         LL val;
    43         scanf("%I64d",&val);
    44         a[i].sum=a[i-1].sum+val;
    45         a[i].p=i;
    46     }
    47     a[n+1].sum=0;
    48     a[n+1].p=n+1;
    49     std :: sort(a+1,a+n+2,cmp);
    50     int t=0;
    51     for(int i=1;i<=n+1;i++){
    52         if(i==1||a[i].sum!=a[i-1].sum) ++t;
    53         p[a[i].p]=t;
    54     }
    55     update(p[n+1],1);
    56     LL temp=0;
    57     for(int i=1;i<=n;i++){
    58         temp=cal(p[i]);
    59         update(p[i],temp);
    60     }
    61     printf("%I64d",temp);
    62 }
    View Code
  • 相关阅读:
    SQL Server 限制IP登陆
    提高MSSQL数据库读取速度,降低CPU损耗
    Windows Azure 平台开发基础系列视频
    AutoFac使用方法总结:Part III
    Python学习笔记 01 快速入门
    黑苹果~~
    Python学习笔记 02 Python基础
    Python学习笔记 04 数字
    Python学习笔记 03 Python对象
    Gridview导出excel范例
  • 原文地址:https://www.cnblogs.com/Blacko/p/3381924.html
Copyright © 2011-2022 走看看