zoukankan      html  css  js  c++  java
  • codeforces 961E Tufurama

    题目链接:http://codeforces.com/contest/961/problem/E

    题意:给你n个数ai,(n<=2e5,1<=ai<=1e9)然后问你在这n个数中,有多少对i,j(i<j)满足ai>=j&&aj>=i。输出对数即可

    分析:首先我们知道对于满足要求的i,j,我们需要满足ai>j和aj>i。然后我们枚举i,那么可以确定j的范围是1到ai。我们可以枚举1到ai范围内的j可以求出每个与i满足的个数,这样时间复杂度是O(n²),显然要T。仔细一想,我们的i是递增+1枚举,因此我们可以每次枚举完之后删除等于i的数就可以了。我们需要区间查询和单点更新(树状数组就可以了)。由于i是从1开始到n,我们在每次查询完之后,删除aj等于i的数字,完成更新。这样可以保证我们下次枚举i+1的时候,查询得到的aj一定是大于i+1的。然后我们需要去除i和i对,然后除以2以确保i<j。(我的数据结构是真的菜,一般都是靠躺)

    AC代码:

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 long long a[200005];
     6 int n;
     7 vector<int>G[200005];
     8 int lowbit(int x){
     9     return x&(-x);
    10 }
    11 void update(int x,long long d){
    12     while(x<=n){
    13         a[x]+=d;
    14         x+=lowbit(x);
    15     }
    16 }
    17 long long query(int x){
    18     long long sm=0;
    19     while(x){
    20         sm+=a[x];
    21         x-=lowbit(x);
    22     }
    23     return sm;
    24 }
    25 int b[200005];
    26 int main(){
    27     ios_base::sync_with_stdio(0);
    28     cin.tie(0);
    29     memset(a,0,sizeof(a));
    30     cin>>n;
    31     n++;
    32     for(int i=1;i<n;i++){
    33         cin>>b[i];
    34         if(b[i]>=n){
    35             b[i]=n;
    36         }
    37         G[b[i]].push_back(i);
    38         update(i,1);
    39     }
    40     long long result=0;
    41     for(int i=1;i<n;i++){
    42         long long sm1=query(b[i]);
    43         result+=sm1;
    44         if(b[i]>=i) result--;
    45         int d=G[i].size();
    46         for(int j=0;j<d;j++){
    47             update(G[i][j],-1);
    48         }
    49     }
    50     cout<<result/2<<endl;
    51 return 0;
    52 }
    View Code
  • 相关阅读:
    String 方法
    异常处理
    数组长度改变方法
    对象
    重载(函数)
    函数
    java基础(死循环退出选项)
    cookie的封装,获取,删除
    事件监听的理解
    JS少数兼容
  • 原文地址:https://www.cnblogs.com/ls961006/p/8782940.html
Copyright © 2011-2022 走看看