zoukankan      html  css  js  c++  java
  • JOI 2012 fish 题解

    题目大意:

    给你一个0/1/2序列Ai,每个值Ai有一个权值Pi。如果两个值的权值PiPj满足Pi2Pj,那么Ai就会把Aj吔掉,也就是说Ai, Aj不能共存。

    Ai的一个子序列的特征三元组为(Sum0, Sum1, Sum2),其中Sump为子序列中的Ai=p的个数。当然这里要求所有值可以共存。

    求:Ai的所有合法子序列的特征三元组的种类数目。1N200000

    这道题可谓是难题(对于我),同样是听完题解外加问人外加参考代码才回的,我们给个原题网址(日文版)戳一下http://www.ioi-jp.org/camp/2012/2012-sp-tasks/

    首先我们现将p从小到大排一下序,此时我们可以求出对于每一个i它的极大三元组,就是对于每一个i,求一个最大的j,使得pj<pi*2,那么统计i到j中的0,1,2的个数,记它为极大三元组,我们记这n个极大三元组为a,b,c。

    如果将a,b,c放入立体三维空间中,那么问题就转换为了求这些立方体(0,0,0到a,b,c)的体积并,只要在立方体里面的点就一定满足条件,这显然是比较难求的,但是如果我们把它转换为二维,问题就简单了很多。

    首先我们将它们以a从小到大排序,然后依次在平面内加入点(b,c),我们可以发现,对于任意a'>a,满足a'的所有b,c一定在a下一定成立,所以每次在统计a的时候,要加上之前>a的面积并。并且我们发现,每一时刻面积并的形状都是阶梯状的,也就是说,b越大c越小,所以可以每次加进来一个点,只需要判断它是否在图形外,在图形外,则要更新面积以及在边缘的点,这就体现了c++的好处,巧用set,就可以避免写平衡树了。贴几张原题题解图

         +-----+-----+                     
        /     /     /|
       +-----+-----+ |
      /     /     /| +
    +-----+-----+ |/|
    |     |     | + |
    |     |     |/| +
    +-----+-----+ |/|
    |     |     | + |
    |     |     |/| +
    +-----+-----+ |/
    |     |     | +
    |     |     |/
    +-----+-----+ 

         +-----+-----+
        /0,2,1/1,2,1/|
       +-----+-----+ |
      /     /     /| +
    +-----+-----+ |/|
    |     |     | + |
    |0,2,0|1,2,0|/| +
    +-----+-----+ |/|
    |     |     | + |
    |0,1,0|1,1,0|/| +
    +-----+-----+ |/
    |     |     | +
    |0,0,0|1,0,0|/
    +-----+-----+ 

           +---------+
          /         /|
         /         / |
        +---------+  |
        |         |  +--------+
        +------+  | /        /|
       /      /|  |/        / +-----+
      /      / ;--+        / /     /|
    +------+ +-----------+ +-----+ +
    |      | |           | |     |/
    |      | |           | +-----+
    |      | |           |/
    |      | +-----------+
    |      |/
    +------+    

    +--+--+----+----+---+-->
    |  |  |    |    |   |
    +--+--+----+----+---@
    |  |  |    |    |
    +--+--+----@    |
    |  |  |         |
    +--+--+---------@
    +--+--@
    |  |
    |  |
    +--@
    |
    V

     +-------------------+-->
    |                   |
    |               +---@
    |               |
    |               |
    |               |
    |     +---------@
    |  +--@
    |  |
    |  |              o <-- たとえばこの点を追加するとします
    +--@
    |
    V
     +-------------------+-->
    |                   |
    |               +-+-@
    |               | |
    |               | |
    |               | |
    |     +---------@ |
    |  +--@           |
    |  |              |
    |  +--------------o
    +--@
    |
    V

    +-------------------+-->
    |                   |
    |                 +-@
    |                 |
    |                 |
    |                 |
    |               ; |
    |     ;           |
    |                 |
    |  +--------------o
    +--@
    |
    V

    可能讲的不清楚,具体看代码吧。

     

      1 #include<iostream>
      2 #include<set>
      3 #include<cstdio>
      4 #include<algorithm>
      5 using namespace std;
      6 int n;
      7 const int maxn=200005;
      8 struct node
      9 {
     10     int type,val;
     11 }a[maxn];
     12 struct three
     13 {
     14     int a,b,c;
     15 }d[maxn];
     16 bool cmp(node u,node v)
     17 {
     18     return u.val<v.val;
     19 }
     20 int now;
     21 bool ff(three u,three v)
     22 {
     23     return u.a>v.a;
     24 }
     25 long long  mian;
     26 set <int> s;
     27 int h[maxn],l[maxn],r[maxn];
     28 void listAdd(int x, int prev)
     29 {
     30     int succ=r[prev];
     31     l[x]=prev;r[prev] = x;
     32     r[x]=succ;l[succ] = x;
     33 }
     34 long long ans;
     35 int main()
     36 {
     37     scanf("%d",&n);
     38     for(int i=1;i<=n;i++)scanf("%d%d",&a[i].type,&a[i].val);
     39     sort(a+1,a+n+1,cmp);
     40 //    for(int i=1;i<=n;i++)cout<<a[i].val<<" ";
     41     int da=0,db=0,dc=0;
     42     for(int i=1;i<=n;i++)
     43     {
     44         if(i!=1)
     45         {
     46             if(a[i-1].type==0)da--;
     47             else if(a[i-1].type==1)db--;
     48             else dc--;
     49         }
     50         while(now<n && a[now+1].val<a[i].val*2)
     51         {
     52             now++;
     53             if(a[now].type==0)da++;
     54             else if(a[now].type==1)db++;
     55             else dc++;
     56         }
     57       //  cout<<da<<" "<<db<<" "<<dc<<endl;
     58         d[i].a=da+1;
     59         d[i].b=db+1;
     60         d[i].c=dc+1;
     61     }
     62     sort(d+1,d+n+1,ff);
     63     
     64     for(int i=1;i<=n;i++)
     65 //    printf("%d %d %d
    ",d[i].a,d[i].b,d[i].c);
     66 
     67     s.clear();
     68     int ll=0,rr=n+2;
     69     l[ll]=l[rr]=ll;
     70     r[ll]=r[rr]=rr;
     71     h[ll]=rr;
     72     h[rr]=ll;
     73     s.insert(ll);
     74     s.insert(rr);
     75     for(int i=1;i<=n;i++)
     76     {
     77         ans+=mian*(long long)(d[i-1].a-d[i].a);
     78     //    cout<<ans<<endl;    
     79     
     80         int x=d[i].b;
     81         int y=d[i].c;
     82         if(!s.count(x))
     83         {
     84             int succ=*s.lower_bound(x);
     85             s.insert(x);
     86             listAdd(x,l[succ]);
     87             h[x]=h[succ];
     88         }
     89         while(true)
     90         {
     91             if(h[x]>=y)break;
     92             mian+=((long long)y-h[x])*((long long)x-l[x]);
     93             h[x]=y;
     94             x=l[x];
     95         }
     96         //cout<<i<<endl;
     97         x=d[i].b;
     98         while(h[l[x]]==h[x])
     99         {
    100             int tx=l[x];
    101             r[l[tx]]=r[tx];
    102             l[r[tx]]=l[tx];
    103             s.erase(tx);
    104         }
    105     //    cout<<i<<endl;
    106         //cout<<"find"<<endl;
    107     }
    108     ans+=mian*d[n].a;
    109     cout<<ans<<endl;
    110     return 0;
    111 }
    View Code

     

     

  • 相关阅读:
    jquery easyui DataGrid
    jquery-easyui中表格的行编辑功能
    C# 序列化与反序列化几种格式的转换
    ASP.NET中JSON的序列化和反序列化
    市委组织部考核项目——利用EasyUi中可编辑的DataGrid控件对多行数据进行编辑并提交
    easyui datagrid 添删改(纪录)
    easyui datagrid
    JS页面间传值
    JQuery下focus()无法自动获取焦点的处理方法 jquery如何使文本框获得焦点
    jQuery插件 -- Form表单插件jquery.form.js
  • 原文地址:https://www.cnblogs.com/sillygirl/p/3908436.html
Copyright © 2011-2022 走看看