• Luogu P5070 [Ynoi2015]即便看不到未来


    回坑做ynoi,然后发现自己的脑子就是一团浆糊

    首先仔细阅读题目,我们发现由于是对于询问的区间先排序后在讨论(刚开始看错了以为不可做题),所以显然可以离线一波

    把询问按右端点从小到大排,每次加入右边的位置然后询问左端点的答案

    考虑加入一个数之后的贡献,容易发现有四种:

    1. 这个数不和之前的任何数相邻,单独加上(1)的贡献
    2. 这个数在一边和之前的数相邻,要把原来的贡献减(1)然后加上现在(1)的贡献
    3. 这个数在两边都和其他数相邻,把两边的贡献都减了然后加上这一段长的
    4. 这个数以前出现过了,那么只处理从上次出现位置到当前位置的贡献变化

    然后我们容易把贡献的影响归为一类,即对于加入的(a_i),若((a_i-fr,a_i))((a_i,a_i+bk))均出现过

    那么删除((a_i-fr,a_i))((a_i,a_i+bk))的贡献然后加入((a_i-fr,a_i+bk))的贡献即可

    然后我们发现这个东西和答案都不大好维护的样子,那不是GG

    细细一看题目原来查询的区间长度都是(le 10)的,那么就意味着我们每次只需要暴力扫一遍((a_i-11,a_i))((a_i,a_i+11))即可进行更新

    同理我们也可以直接开(10)个树状数组来维护贡献,具体地直接记录后缀和即可

    注意更新贡献的时候要从后往前做才能防止重漏

    具体实现详见代码

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<iostream>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=1e6+5;
    struct ques
    {
    	int l,r,id;
    	friend inline bool operator < (const ques& A,const ques& B)
    	{
    		return A.r<B.r;
    	}
    }q[N];
    struct data
    {
    	int x,y;
    	friend inline bool operator < (const data& A,const data& B)
    	{
    		return A.x>B.x;
    	}
    }p[50];
    int n,m,mx,tot,a[N],lst[N]; char ans[N][11];
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		char Fin[S],*A,*B;
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		#undef tc
    }F;
    class TreeArray
    {
    	private:
    		int bit[N];
    		#define lowbit(x) (x&-x)
    	public:
    		inline void add(RI x,CI y)
    		{
    			for (;x;x-=lowbit(x)) bit[x]+=y;
    		}
    		inline int get(RI x,int y=0)
    		{
    			for (;x<=n;x+=lowbit(x)) y+=bit[x]; return y;
    		}
    		#undef lowbit
    }BIT[11];
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	RI i; for (F.read(n),F.read(m),i=1;i<=n;++i) F.read(a[i]),mx=max(mx,a[i]);
    	for (i=1;i<=m;++i) F.read(q[i].l),F.read(q[i].r),q[i].id=i;
    	for (sort(q+1,q+m+1),tot=i=1;i<=n;++i)
    	{
    		RI cnt=0,j,fr=0,bk=0; for (j=max(1,a[i]-11);j<=min(mx,a[i]+11);++j)
    		if (lst[j]>lst[a[i]]) p[++cnt]=(data){lst[j],j}; p[++cnt]=(data){i,a[i]};
    		for (p[cnt+1].x=lst[a[i]],sort(p+1,p+cnt+1),j=1;j<=cnt;++j)
    		{
    			if (p[j].y<a[i]) while (fr<=10&&(a[i]-fr-1==p[j].y||lst[a[i]-fr-1]>p[j].x)) ++fr;
    			if (p[j].y>a[i]) while (bk<=10&&(a[i]+bk+1==p[j].y||lst[a[i]+bk+1]>p[j].x)) ++bk;
    			if (1<=fr&&fr<=10) BIT[fr].add(p[j].x,-1),BIT[fr].add(p[j+1].x,1);
    			if (1<=bk&&bk<=10) BIT[bk].add(p[j].x,-1),BIT[bk].add(p[j+1].x,1);
    			if (fr+bk+1<=10) BIT[fr+bk+1].add(p[j].x,1),BIT[fr+bk+1].add(p[j+1].x,-1);
    		}
    		lst[a[i]]=i; while (tot<=m&&q[tot].r==i)
    		{ for (j=1;j<=10;++j) ans[q[tot].id][j]=BIT[j].get(q[tot].l)%10+48; ++tot; }
    	}
    	for (i=1;i<=m;++i) puts(ans[i]+1); return 0;
    }
    
  • 相关阅读:
    文件上传---普通文件fileupload.jar和url文件httpUrlConnection
    HttpClient学习整理
    编写更少量的代码:使用apache commons工具类库
    多线程进阶
    多线程下HashMap的死循环问题
    线程本地变量ThreadLocal源码解读
    Eclipse工作常见问题总结
    Java集合---ConcurrentHashMap原理分析
    Java集合---Arrays类源码解析
    Java集合---LinkedList源码解析
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12865120.html
Copyright © 2020-2023  润新知