zoukankan      html  css  js  c++  java
  • 【洛谷P5677】[GZOI2017]配对统计

    前言

    【题目传送门】
    难度:上蓝有余,上紫不足。
    做题用时:(1h 45min)。(还因为一个符号写反的下饭问题调了一会)
    一开始没有看到数字两两不同的限制条件,直接 gg 了,看了题解。
    感觉不是特别难,但是也有点绕,主要是排序的东西太多了。

    题解

    首先根据数字从小到大排序,就能找到每一个数字的配对数字。(排序 1)
    配对之后把每一对数字的位置按照右端点排序。(排序 2)
    把询问离线,按照右端点排序。(排序 3)
    接下来的操作大概和“HH 的项链”异曲同工了。
    不断按照询问把当前区间右端点向右更新。
    似乎就切掉了...?

    代码

    看着很长但是千万不要害怕,理清思路也就是一遍的事。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF = 0x3f3f3f3f,N = 3e5+10;
    inline ll read()
    {
    	ll ret=0;char ch=' ',c=getchar();
    	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
    	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    int n,m;
    ll ans; 
    struct node //用来找好对 
    {
    	int val,id;
    	bool operator <(const node &oth) const 
    	{return val<oth.val;}
    }w[N];//n
    int tot;
    struct Pair//存好对 
    {
    	int l,r;
    	bool operator <(const Pair &oth) const 
    	{return r<oth.r;}
    }a[N<<1];//tot
    struct ask//询问离线 
    {
    	int l,r,id;
    	bool operator <(const ask &oth) const 
    	{return r<oth.r;}
    }q[N];//m
    struct BIT//树状数组 
    {
    	int c[N];
    	inline void update(int x,int v)
    	{
    		for(int i=x;i<=n;i+=i&-i) c[i]+=v;
    	}
    	inline int query(int x)
    	{
    		int ret=0;
    		for(int i=x;i;i-=i&-i) ret+=c[i];
    		return ret;
    	}
    }tr;
    void find_pair()//找好对 
    {
    	sort(w+1,w+n+1); 
    	for(int i=1;i<=n;i++)	
    	{
    		if(i==1) a[++tot]=(Pair){min(w[i].id,w[i+1].id),max(w[i].id,w[i+1].id)};
    		else if(i==n) a[++tot]=(Pair){min(w[i].id,w[i-1].id),max(w[i].id,w[i-1].id)};
    		else 
    		{
    			if(abs(w[i].val-w[i-1].val)==abs(w[i].val-w[i+1].val))
    			{
    				a[++tot]=(Pair){min(w[i].id,w[i+1].id),max(w[i].id,w[i+1].id)};
    				a[++tot]=(Pair){min(w[i].id,w[i-1].id),max(w[i].id,w[i-1].id)};
    			}
    			else if(abs(w[i].val-w[i-1].val)>abs(w[i].val-w[i+1].val)) 
    				 a[++tot]=(Pair){min(w[i].id,w[i+1].id),max(w[i].id,w[i+1].id)};
    			else a[++tot]=(Pair){min(w[i].id,w[i-1].id),max(w[i].id,w[i-1].id)};
    		}
    	}
    	sort(a+1,a+tot+1); 
    	//for(int i=1;i<=tot;i++)	printf("Pair(%d,%d)
    ",a[i].l,a[i].r);
    }
    void work()
    {
    	int pl=1;
    	for(int i=1;i<=m;i++)	
    	{
    		while(pl<=tot&&a[pl].r<=q[i].r) 
    		{
    			tr.update(a[pl].l,1);
    			pl++;
    		}
    	//	printf("query(%d,%d) : return %d
    ",q[i].l,q[i].r,tr.query(q[i].r)-tr.query(q[i].l-1));
    		ans+=1LL*q[i].id*(pl-1-tr.query(q[i].l-1));
    	}
    	printf("%lld
    ",ans);
    	return;
    }
    int main()
    {
    	n=read(),m=read();
    	if(n==1) return puts("0"),0;//特判 
    	for(int i=1;i<=n;i++) w[i].val=read(),w[i].id=i;
    	find_pair();
    	for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
    	sort(q+1,q+m+1);
    	work();
    	return 0;
    }
    /* 
    5 2
    1 2 3 4 5
    2 4 
    1 5
    */
    
  • 相关阅读:
    Java设计模式之依赖倒置原则
    windows 下安装apache 遇到的问题
    Java序列化相关
    批量插入————优化
    接口相关
    Redis使用及工具类
    面试回顾——kafka
    面试回顾——List<T>排序
    Java面试——线程池
    面试回顾——session相关
  • 原文地址:https://www.cnblogs.com/conprour/p/15511248.html
Copyright © 2011-2022 走看看