zoukankan      html  css  js  c++  java
  • qbxt DAY3 T4

    DAY3 T4

    显然枚举区间不现实,考虑常用套路:计算每一个值的贡献,即被多少个区间经过

    当确定中间点(j)后,对于(i<j,k>j, a_i >a_j, a_k > a_j),发现包含(a_i)的区间左端点有(i)个,包含(a_k)的区间右端点有(n-k+1)个,则包含((i,j,k))这个三元组的区间有(i*(n-k+1))

    建立一个值域树状数组,先对数组从前向后遍历,设(pre[i])表示(i)之前有多少区间经过。每次将树状数组下标为(a_i)的点加上(i)用来计算下一次询问的答案。然后从后向前遍历,做法和前面的相同。

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    
    using namespace std;
    
    #define lb(x) ((x)&(-(x)))
    
    const int maxn=100010;
    
    int n,z[maxn];
    
    long long y[maxn],pre[maxn],suf[maxn];
    
    long long query(int p)
    {
    	long long ans=0;
    	for (;p;p-=lb(p))
    		ans+=y[p];
    	return ans;
    }
    
    void modify(int p,int v)
    {
    	for (;p<=n;p+=lb(p))
    		y[p]+=v;
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int a=1;a<=n;a++)
    		scanf("%d",&z[a]);
    
    	memset(y,0,sizeof(y));
    	for (int a=1;a<=n;a++)
    	{
    		pre[a]=query(n)-query(z[a]);
    		modify(z[a],a);
    	}
    	for(int i = 1; i <= n; i ++) printf("%d ", pre[i]);
    	printf("
    ");
    	memset(y,0,sizeof(y));
    	for (int a=n;a>=1;a--)
    	{
    		suf[a]=query(n)-query(z[a]);
    		modify(z[a],n-a+1);
    	}
    	for(int i = 1; i <= n; i ++) printf("%d ", suf[i]);
    	long long ans=0;
    	for (int a=1;a<=n;a++)
    		ans+=pre[a]*suf[a];
    	//printf("%lld
    ",ans);
    
    	return 0;
    }
    
  • 相关阅读:
    Oracle 实现数据表插入时主键列自增
    Java BigDecimal 加减乘除用法
    php最常见最经典的算法题(1)
    2、php-选择排序方法
    1、php-冒泡排序方法
    65G-一系列Go语言课程Go基础知识高级Go项目战斗New Go语言和区块链开发实践课程
    css
    python基础
    SEO优化指南
    转载GXT之旅
  • 原文地址:https://www.cnblogs.com/lcezych/p/13827609.html
Copyright © 2011-2022 走看看