zoukankan      html  css  js  c++  java
  • 【整体二分】——洛谷P3527 [POI2011]MET-Meteors

    GO:

    整体二分作为一个常考的比较有趣的算法(就是难),可以巧妙的解决一些本来比较复杂的题目(比如静态区间第k大),作为一个oier,掌握整体二分的思想是很有必要的。


    题目描述

    Byteotian Interstellar Union (BIU) has recently discovered a new planet in a nearby galaxy. The planet is unsuitable for colonisation due to strange meteor showers, which on the other hand make it an exceptionally interesting object of study.

    The member states of BIU have already placed space stations close to the planet's orbit. The stations' goal is to take samples of the rocks flying by.

    The BIU Commission has partitioned the orbit into mm sectors, numbered from 11 to mm, where the sectors 11 and mm are adjacent. In each sector there is a single space station, belonging to one of the nn member states.

    Each state has declared a number of meteor samples it intends to gather before the mission ends. Your task is to determine, for each state, when it can stop taking samples, based on the meter shower predictions for the years to come.

    输入格式

    The first line of the standard input gives two integers, nn and mm (1le n,mle 300 0001n,m300 000), separated by a single space, that denote,respectively, the number of BIU member states and the number of sectors the orbit has been partitioned into.

    In the second line there are mm integers o_ioi (1le o_ile n1oin),separated by single spaces, that denote the states owning stations in successive sectors.

    In the third line there are nn integers p_ipi (1le p_ile 10^91pi109),separated by single spaces, that denote the numbers of meteor samples that the successive states intend to gather.

    In the fourth line there is a single integer kk (1le kle 300 0001k300 000) that denotes the number of meteor showers predictions. The following kk lines specify the (predicted) meteor showers chronologically. The ii-th of these lines holds three integers l_i,r_i,a_ili,ri,ai (separated by single spaces), which denote that a meteor shower is expected in sectors l_i,l_{i+1},...,r_ili,li+1,...,ri(if l_ile r_iliri) or sectors l_i,l_{i+1},...,m,1,...,r_ili,li+1,...,m,1,...,ri (if l_i>r_ili>ri) , which should provide each station in those sectors with a_iaimeteor samples (1le a_ile 10^91ai109).

    输出格式

    Your program should print nn lines on the standard output.

    The ii-th of them should contain a single integer w_iwi, denoting the number of shower after which the stations belonging to the ii-th state are expected to gather at least p_ipi samples, or the word NIE (Polish for no) if that state is not expected to gather enough samples in the foreseeable future.

      这个题目和普通的整体二分略有不同,它是环形的,区间[l,r]存在l>r的情况,所以二分的时候注意修改的区间是即可。

      可以考虑在处理询问的时候给每个询问打个标记,区分是绕过背面的弧还是正面的顺弧。

      要注意卡常。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int N=600010;
      5 int n,m,kk;
      6 int num[N],ans[N];
      7 struct node{
      8     int l,r,id;
      9     ll k;
     10     int tp;
     11 }q[N],q1[N],q2[N];
     12 vector<int> t[N];
     13 // fast read----------------------------------------
     14 inline int read(){
     15     int x=0,f=1;
     16     char c=getchar();
     17     while(!isdigit(c)){
     18         if(c=='-'){
     19             f=-1;
     20         }
     21         c=getchar();
     22     }
     23     while(isdigit(c)){
     24         x=x*10+c-'0';
     25         c=getchar();
     26     }
     27     return x*f;
     28 }
     29 // tree array----------------------------------------
     30 inline ll arr[N];
     31 inline ll lb(int x){return x&(-x);}
     32 inline void add(int x,int y){for(;x<=m;x+=lb(x))arr[x]+=y;}
     33 inline ll ask(int x){ll ans_=0;for(;x;x-=lb(x))ans_+=arr[x];return ans_;}
     34 
     35 // get ans--------------------------------------------
     36 void solve(int l,int r,int L,int R){
     37     if(L>R) return;
     38     if(l==r){
     39         for(int i=L;i<=R;i++){
     40             if(q[i].tp==1){
     41                 ans[q[i].id]=l;
     42             }
     43         }
     44         return;
     45     }
     46     int mid=(l+r)>>1,cnt1=0,cnt2=0;
     47     for(register int i=L;i<=R;i++){
     48         if(q[i].tp==1){
     49             ll sum=0;
     50             for(int j=0;j<t[q[i].id].size();j++){
     51                 sum+=ask(t[q[i].id][j]);
     52                 if(sum>q[i].k){
     53                     break;
     54                 }
     55             }
     56             if(sum>=q[i].k){
     57                 q1[++cnt1]=q[i];
     58             }
     59             else{
     60                 q[i].k-=sum;
     61                 q2[++cnt2]=q[i];
     62             }
     63         }
     64         else{
     65             if(q[i].id<=mid){
     66                 if(q[i].tp==2){
     67                     add(q[i].l,q[i].k);add(q[i].r+1,-q[i].k);
     68                 }
     69                 else{
     70                     add(1,q[i].k);add(q[i].r+1,-q[i].k);add(q[i].l,q[i].k);
     71                 }
     72                 q1[++cnt1]=q[i];//更新mid左边的答案。 
     73             }
     74             else{
     75                 q2[++cnt2]=q[i];//如果在右边就放到q2去。 
     76             }
     77         }
     78     }
     79     for(register int i=L;i<=R;i++)if(q[i].id<=mid&&q[i].tp!=1){
     80         if(q[i].tp==2){
     81             add(q[i].l,-q[i].k);add(q[i].r+1,q[i].k);
     82         }
     83         else{
     84             add(1,-q[i].k);add(q[i].r+1,q[i].k);add(q[i].l,-q[i].k);
     85         }
     86     } 
     87     for(register int i=1;i<=cnt1;i++){
     88         q[i+L-1]=q1[i];
     89     }
     90     for(register int i=1;i<=cnt2;i++){
     91         q[L+i+cnt1-1]=q2[i];
     92     }
     93     solve(l,mid,L,L+cnt1-1);
     94     solve(mid+1,r,L+cnt1,R);
     95 }
     96 int main(){
     97     n=read(),m=read();
     98     for(register int i=1;i<=m;i++){
     99         t[read()].push_back(i);
    100     }
    101     for(register int i=1;i<=n;i++){
    102         num[i]=read();
    103     }
    104     kk=read();
    105     for(register int i=1;i<=kk;i++){
    106         q[i].l=read();q[i].r=read();q[i].k=read();
    107         q[i].id=i;
    108         q[i].tp=(q[i].r>=q[i].l?2:3);
    109     }
    110     for(register int i=1;i<=n;i++){
    111         q[i+kk].k=num[i];
    112         q[i+kk].tp=1;
    113         q[i+kk].id=i;
    114     }
    115     solve(1,kk+1,1,kk+n);
    116     for(register int i=1;i<=n;i++){
    117         if(ans[i]!=kk+1) printf("%d
    ",ans[i]);
    118         else printf("NIE
    ");
    119     }
    120     return 0;
    121 }
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    Ubuntu虚拟机磁盘空间不足的解决
    eclipse启动报错 JVM terminated. Exit code=1
    Ubuntu16.04 安装eclipse
    HDU 1710 Binary Tree Traversals(二叉树)
    Ubuntu16.04 搭建伪分布式Hadoop环境
    HDU 1560 DNA sequence(IDA*)
    Go的函数
    Go的包
    Go语言开发环境搭建
    go的循环
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11404843.html
Copyright © 2011-2022 走看看