• Master of Sequence(数学+二分+树状数组)


    题意:给两个长度为n的序列(a1,a2......,an)、(b1,b2......bn)和m个询问以及一个整数k,找出满足k <= S(t) = Σ(i=1 to n) ((t-bi) / ai)向下取整  的最小t。考虑函数的单调性此题可以二分,对于该式子可以证明 ((t-bi) / ai)向下取整的值就是 (t/ai)向下取整的值减去 (bi/ai)向下取整的值 如果 (t%ai) - (bi%ai) 的值比0小,说明还得到前面算出来的(t/ai)的值那里拿一个1来减, 所以算出来的值应该减1。 考虑a的值小于1000,用1000个树状数组维护每个(bi % ai)的前缀和,用一个大小为1000的数组nums维护每个ai出现的次数,用一个变量sum记录Σ(i=1 to n)bi/ai的和,则对于每个t,S(t)可以通过以下方式计算得到:i从for 1到1000 记录(t/i) * nums[ai]的值,这个值减去sum得到的是未经过取余处理的值,然后i 从1for到1000的过程中可以减去 (bi %ai)比(t%i)大的个数,这个数可以通过树状数组查询(getsum(t%ai))表示查找<=t%ai的数 然后用总个数nums[ai]减去它得到。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 1e3+10;
     5 const int maxm = 1e5+10;
     6 int t,n,m,op;
     7 ll x,y,k;
     8 ll a[maxm],b[maxm];
     9 int nums[maxn];
    10 int lowbit(int x) {return x&(-x);}
    11 struct tree{
    12     int c[maxn];
    13     inline void update(int x,int y){
    14         x++;
    15         for(int i=x;i<maxn;i+=lowbit(i))
    16         c[i] += y;
    17     }
    18     inline int getsum(int x){
    19            int ans = 0;x++;
    20            for(int i=x;i;i-=lowbit(i))
    21            ans += c[i];
    22         return ans;
    23     }
    24 }node[maxn];
    25 bool check(ll t){
    26     ll tmp = 0;
    27     for (int i = 1; i <= 1000; i++){
    28         tmp += (t / i) * nums[i] - (nums[i] - node[i].getsum(t % i));
    29         if (tmp >= k + 1000 - i) return true;
    30     }
    31     return tmp >= k;
    32 }
    33 int main(){
    34     scanf("%d",&t);
    35     while (t--){
    36         ll sum = 0;
    37         memset(nums, 0, sizeof nums);
    38         memset(node, 0, sizeof node);        
    39         scanf("%d%d",&n,&m);
    40         for (int i = 1; i <= n; i++){
    41             scanf("%lld",&a[i]);
    42             nums[a[i]]++;
    43         }
    44         for (int i = 1; i <= n; i++){
    45             scanf("%lld",&b[i]);
    46             sum += b[i] / a[i];
    47             node[a[i]].update(b[i]%a[i],1);
    48         }
    49         while (m--){
    50             scanf("%d",&op);
    51             if (op == 1){
    52                 scanf("%lld%lld",&x,&y);
    53                 nums[a[x]]--,nums[y]++;
    54                 node[a[x]].update(b[x] % a[x], -1);
    55                 node[y].update(b[x] % y, 1);
    56                 sum = sum - b[x] / a[x] + b[x] / y;
    57                 a[x] = y;
    58             }
    59             else if (op == 2){
    60                 scanf("%lld%lld",&x,&y);
    61                 node[a[x]].update(b[x]%a[x], -1);
    62                 node[a[x]].update(y%a[x], 1);
    63                 sum = sum - b[x] / a[x] + y / a[x];
    64                 b[x] = y;
    65             }
    66             else{
    67                 scanf("%lld",&k);
    68                 ll l = 0, r = 1e12, ans;
    69                 k += sum;
    70                 while (l <= r){
    71                     ll mid = (l + r) >> 1;
    72                     if (check(mid)) {
    73                         ans = mid;
    74                         r = mid-1;
    75                     }
    76                     else l = mid + 1;
    77                 }
    78                 printf("%lld
    ",ans);
    79             }
    80         }
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    C#: 抓取网页类(获取网页中所有信息)
    web application stress tool(WAS) 使用方法
    迁移数据到历史表SQL .
    jquery 获取 自定义属性(attr 和 prop)
    C#: json字符串中的特殊字符处理
    asp.net : 拒绝频繁的IP访问
    SQL : 自动生成订单编号
    WCF: 已超过传入消息(65536)的最大消息大小配额。若要增加配额,请使用相应绑定元素上的 MaxReceivedMessageSize 属性。
    SQL: 随机从数据库取值
    WCF:读取 XML 数据时,超出最大字符串内容长度配额 (8192)。通过更改在创建 XML 读取器时所使用的 XmlDictionaryReaderQuotas 对象的 MaxStringContentLength 属性,可增加此配额。
  • 原文地址:https://www.cnblogs.com/hznudreamer/p/12665014.html
Copyright © 2020-2023  润新知