bzoj 1926: [Sdoi2010]粟粟的书架

  1 #include<cstdio>
  2 #include<iostream>
  3 #define N 201
  4 #define M 500008
  5 using namespace std;
  6 int cnt,r,c,m,ls[20*M],rs[20*M],root[M],ans,sum[20*M],sum1[20*M],shu,num[1008][N][N],num1[1008][N][N];
  7 void jia(int l,int r,int x,int &y,int v)
  8 {
  9     y=++cnt;
 10     sum[y]=sum[x]+v;
 11     sum1[y]=sum1[x]+1;
 12     if(l==r)
 13       return;
 14     ls[y]=ls[x];
 15     rs[y]=rs[x];
 16     int mid=(l+r)>>1;
 17     if(v<=mid)                
 18       jia(l,mid,ls[x],ls[y],v);
 19     else
 20       jia(mid+1,r,rs[x],rs[y],v);
 21     return;
 22 }
 23 int xun(int a1,int a2,int l,int r,int v)
 24 {
 25     if(!a1)
 26       return 0;
 27     if(l>=v)
 28       {
 29         shu-=sum[a1]-sum[a2];
 30         return sum1[a1]-sum1[a2];
 31       }
 32     int s=0,mid=(l+r)>>1;
 33     if(mid>=v)
 34       s+=xun(ls[a1],ls[a2],l,mid,v);
 35     s+=xun(rs[a1],rs[a2],mid+1,r,v);
 36     return s;
 37 }
 38 void solve1()
 39 {
 40     for(int i=1;i<=c;i++)
 41       {
 42         int a1;
 43         scanf("%d",&a1);
 44         jia(1,1000,root[i-1],root[i],a1);
 45       }
 46     for(int i=1;i<=m;i++)
 47       {
 48         int x0,y0,x1,y1,v;
 49         scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&v);
 50         int l=0,r=1000,mid=(l+r)>>1,b1,md,md1;
 51         ans=0;
 52         for(;l<=r;)
 53           {
 54             shu=v;
 55             b1=xun(root[y1],root[y0-1],1,1000,mid);
 56             if(shu<=0)
 57             {
 58                 md1=v-shu;
 59                 md=mid;
 60                 ans=b1;
 61                 l=mid+1;
 62             }
 63             else
 64               r=mid-1;
 65             mid=(l+r)>>1;
 66           }
 67         if(!ans)
 68           printf("Poor QLW
");
 69         else
 70           {
 71             int a1;
 72             r=xun(root[y1],root[y0-1],1,1000,md+1);
 73             r=ans-r;
 74             l=0;
 75             mid=(l+r)>>1;
 76             for(;l<=r;)
 77               {
 78                 if(md1-mid*md>=v)
 79                   {
 80                     a1=ans-mid;
 81                     l=mid+1;
 82                   }
 83                 else
 84                   r=mid-1;
 85                 mid=(l+r)>>1;
 86               }
 87             printf("%d
",a1);
 88           }
 89       }
 90     return;
 91 }
 92 void solve2()
 93 {
 94     for(int i=1;i<=r;i++)
 95       for(int j=1;j<=c;j++)
 96         {
 97             int a1;
 98             scanf("%d",&a1);
 99             for(int k=0;k<=1000;k++)
100               {
101                 num[k][i][j]=(num[k][i][j-1]+num[k][i-1][j]-num[k][i-1][j-1]);
102                 num1[k][i][j]=(num1[k][i][j-1]+num1[k][i-1][j]-num1[k][i-1][j-1]);
103                 if(a1>=k)
104                   {
105                     num[k][i][j]+=a1;
106                     num1[k][i][j]++;
107                   }
108               }
109         }
110     for(int i=1;i<=m;i++)
111       {
112         int x0,y0,x1,y1,v;
113         scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&v);
114         int l=0,r=1000,mid=(l+r)>>1,tm=0,tm1=0,tm2=0;
115         for(;l<=r;)
116           {
117             if(num[mid][x1][y1]-num[mid][x1][y0-1]-num[mid][x0-1][y1]+num[mid][x0-1][y0-1]>=v)
118               {
119                 tm=num1[mid][x1][y1]-num1[mid][x1][y0-1]-num1[mid][x0-1][y1]+num1[mid][x0-1][y0-1];
120                 tm1=mid;
121                 l=mid+1;
122               } 
123             else
124               r=mid-1;
125             mid=(l+r)>>1;
126           }
127         if(!tm)
128           printf("Poor QLW
");
129         else
130           {
131             tm2=num[tm1][x1][y1]-num[tm1][x1][y0-1]-num[tm1][x0-1][y1]+num[tm1][x0-1][y0-1];
132             l=0,r=num1[tm1+1][x1][y1]-num1[tm1+1][x1][y0-1]-num1[tm1+1][x0-1][y1]+num1[tm1+1][x0-1][y0-1];
133             r=tm-r;
134             mid=(l+r)>>1;
135             for(;l<=r;)
136               {
137                  if(tm2-mid*tm1>=v)
138                    {
139                      ans=tm-mid;
140                      l=mid+1;
141                    }
142                 else
143                   r=mid-1;
144                 mid=(l+r)>>1;
145               }
146             printf("%d
",ans);
147           }
148       }
149     return;
150 }
151 int main()
152 {
153     scanf("%d%d%d",&r,&c,&m);
154     if(r==1)
155       solve1();
156     else
157       solve2();
158     return 0;
159 }

两种情况 对于R,C<=200,用前缀和暴力二分,对于另外的数据,在主席树上二分。

原文地址:https://www.cnblogs.com/xydddd/p/5290269.html