2017国家集训队作业[arc082d]Sandglass

2017国家集训队作业[arc082d]Sandglass

题意:

​ 有一个沙漏,初始时\(A\)瓶在上方,两个瓶子的最大容量都为\(X\)克,沙子流动的速度为\(1g\)每单位时间。给出\(K\)个时间点\(r_1\sim r_K\)表示在这几个时间点,漏斗会上下翻转,无视翻转时间。给出\(Q\)个询问,每个询问两个数\(t_i,a_i\),表示若初始时\(A\)瓶有\(a_i\)克沙子,询问第\(t_i\)单位时间时,\(A\)瓶中会有多少克沙子?(\(X,t_i,r_i\leq 10^9,a_i\leq X,K\leq 10^5\),输入保证序列\(\{r_i\}\)\(\{t_i\}\)为升序)

题解:

​ 最后半小时想出来,真的惨。

​ 观察发现\(A\)瓶中的沙子函数图像由若干个斜率为\(1,-1,0\)的一次函数组成。若存在某一时刻,该函数的斜率为\(0\)(即碰到上下边界),那么在此以后,函数的图像与截距(\(a_i\))无关。

​ 初始截距(\(a_i\))的取值会使该函数出现三种情况:

\(1.\)只会碰到上边界

\(2.\)只会碰到下边界

\(3.\)上下边界都不会碰到

​ 还存在一种情况:无论\(a_i\)的值是什么,该函数总会碰到上或下边界。

​ 分别维护\(a\)的区间即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define of(i,l,r) for(int i=l;i>=r;i--)
#define fe(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
inline int rd()
{
    static int x,f;
    x=0,f=1;
    char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}
const int N=100010;
int X,K,Q,T[N],ty;

struct cha{
	int a1,x1,a2,x2,x;
	bool flag;
	inline int get(int a)
	{
		if(flag)return x;
		if(a<=a1)return x1;
		if(a>=a2)return x2;
		return a-a1+x1;
	}
}c[N];

inline void gao(int i,int tim)
{
	if(c[i].flag){
		c[i].x+=ty*tim;
		c[i].x=max(0,c[i].x);
		c[i].x=min(c[i].x,X);
		return;
	}
	if(ty==-1){
		if(c[i].x2<=tim){
            c[i].flag=1;c[i].x=0;
            return;
        }
        if(tim>=c[i].x1){c[i].a1+=tim-c[i].x1;c[i].x1=0;c[i].x2-=tim;}
        else{c[i].x1-=tim;c[i].x2-=tim;}
	}
	else{
		if(c[i].x1+tim>=X){
			c[i].flag=1;c[i].x=X;
			return;
		}
		if(c[i].x2+tim>=X){c[i].a2-=c[i].x2+tim-X;c[i].x2=X;c[i].x1+=tim;}
		else{c[i].x1+=tim;c[i].x2+=tim;}
	}
}

int main()
{
	freopen("inc.txt","r",stdin);
	X=rd();K=rd();
	c[0].a1=c[0].x1=0;c[0].a2=c[0].x2=X,c[0].x=0;
	c[0].flag=0;ty=-1;
	fo(i,1,K)T[i]=rd(),c[i]=c[i-1],gao(i,T[i]-T[i-1]),ty=-ty;
	int j=0;
	Q=rd();ty=-1;
	fo(i,1,Q){
		int t=rd(),a=rd();
		while((j<K&&T[j+1]<=t))j++,ty=-ty;
		int ans=c[j].get(a);
		ans+=ty*(t-T[j]);
		ans=min(ans,X);
		ans=max(ans,0);
		printf("%d\n",ans);
	}
	return 0;
}

UPD:2018/8/19 补上了代码

posted @ 2018-08-18 20:39  Jackyhh  阅读(253)  评论(0编辑  收藏  举报