11.06练习赛

1106练习赛

T1 焚风现象

一听名字感觉很炫酷结果是道差分水题
就这道水题我交了5+遍才过,总是有些小地方忘打负号

题目大意:
不行题面太炫酷了在下无法解读
有一块近海的地形,用地点0~地点N表示。每个地点有一个高度(地点0高度恒为0,温度也为0)。一个地点的温度与它的高度和前一个地点的高度及温度有关。关系为:

  • 若高度相等,则温度相等。
  • 若\(H_i<H_{i-1}\),每下降一个单位高度温度上升T℃。
  • 反之,每上升一个单位高度温度下降S℃。

由于来自东方的神秘力量,每天该地形的某个区块\((L_i,R_i\)中所有地点的高度会变化\(X_i\)(注意\(X_i\)可以为负值)。
现给出原地形高度,\(S\),\(T\),每天的\(L_i,R_i, X_i\),要求求出每天地点\(N\)的温度。
 

看到区间修改,单点查值,每个地点温度变化量只与上一个地点有关,马上就能想到差分。
所以我们开一个差分数组维护当前地点与上一个地点的高度差。记录一个\(U\)\(D\)值,分别表示一共上升了几个单位长度(Up),下降了几个单位长度(Down)。最后求答案时计算\(D*T-U*S\)即可。
(本人所作的判断过程有些长,但比较容易Get到思路其实就是菜,望理解)
 
那为什么本人此题爆零了呢?
答:在一次修改程序时找出了错误点,但在修改后没有保存。
 
也不好说什么。放代码吧。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std; 
typedef long long ll;
char *p1,*p2,buf[1<<20]; 
#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++))) 
//#define GC getchar() 
inline ll in() 
{ 
    ll ans; 
    char t,k; 
    while(((t=GC)!='-'&&(t>'9'||t<'0'))); 
    k=(t=='-'); 
    ans=k?0:(t-'0'); 
    while((t=GC)>='0'&&t<='9')ans=ans*10+t-'0'; 
    return k?-ans:ans; 
}

const int maxn=200010;
ll a[maxn],x[maxn];
ll n,q,s,t;
ll b[maxn];
ll u,d;
int main()
{
//	freopen("01-01.in","r",stdin);
//	freopen("awind.out","w",stdout);
	ll i,j;
	n=in();q=in();s=in();t=in();
	a[0]=in();
	for(i=1;i<=n;i++)
	{
		a[i]=in();
		if(a[i]>a[i-1])u+=a[i]-a[i-1];
		else d+=a[i-1]-a[i];
		b[i]=a[i]-a[i-1];
	}
	while(q--)
	{
		ll l,r,val;
		l=in();r=in();val=in();
		if(val>0){
			ll b1=b[l]+val,b2=b[r+1]-val;
			if(b[l]<0){
				if(b1>=0){
					d-=abs(b[l]);
					u+=b1;
				}
				else{
					d-=val;
				}
			}
			else{
				u+=val;
			}
			if(r+1>n);
			else
			if(b[r+1]>=0){
				if(b2<=0){
					u-=b[r+1];
					d+=-b2;
				}
				else{
					u-=val;
				}
			}
			else{
				d+=val;
			}
			b[l]=b1;b[r+1]=b2;
		}
		else{
			ll b1=b[l]+val,b2=b[r+1]-val;
			if(b[l]>=0){
				if(b1<=0){
					u-=b[l];
					d+=-b1;
				}
				else{
					u-=-val;
				}
			}
			else{
				d+=-val;
			}
			if(r+1>n);
			else
			if(b[r+1]<0){
				if(b2>=0){
					d-=abs(b[r+1]);
					u+=b2;
				}
				else{
					d-=-val;
				}
			}
			else{
				u+=-val;
			}
			b[l]=b1;b[r+1]=b2;
		}
		printf("%lld\n",d*t-u*s);
		
	}
}

 
 

T2 准高速电车

题面有些难以概括所以直接放原题面其实就是懒

 
nodgd讲了个\(M^2Log_? (N)\)的动归,在此先跳过。
正解为贪心。每次在两个快车站区间枚举,当坐慢车不能到达时就在那个站点设一个准快车站点并把此时可以往后跑的车站存入一个答案数组。
枚举完后把答案数组从大到小排序,将前\(K-M\)个答案加入最终的可到达车站数。
注意最后总答案要减1(不包含1号车站)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
//#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++))) 
#define GC getchar() 
inline ll in() 
{ 
    ll ans; 
    char t,k; 
    while(((t=GC)!='-'&&(t>'9'||t<'0'))); 
    k=(t=='-'); 
    ans=k?0:(t-'0'); 
    while((t=GC)>='0'&&t<='9')ans=ans*10+t-'0'; 
    return k?-ans:ans; 
}
ll n,m,k;
ll a,b,c;
ll t;
ll s[3010];
ll add[3010*3010],cnt;
ll ans;
void gs(ll l,ll r,ll lt)
{
	ll l1=l;
	ll now=l;
	if(lt<0)return;
	ll num=0;
	while(now<r&&num<=k){
		if(lt<0)return;
		ll to=lt/a;
		ll ne=min(r,now+to+1);
		if(now!=l1){
			add[++cnt]=ne-now;
		}
		else ans+=ne-now-1;
		
		lt-=(to+1)*c;
		
		now+=to+1;
		l=now;
		num+=1;
		
	}
}
int main()
{
	n=in();m=in();k=in();a=in();b=in();c=in();t=in();
	ll i,j;
	ll a1=0;
	for(i=1;i<=m;i++)
	{
		s[i]=in();
		if((s[i]-1)*b<=t)a1+=1;
	}
	k-=m;
	for(i=1;i<m;i++)
	{
		gs(s[i],s[i+1],t-(s[i]-1)*b);
	}
	sort(add+1,add+cnt+1);
	for(i=cnt;i>0&&i>cnt-k;i--){
		ans+=add[i];
	}
	printf("%lld\n",a1+ans-1);
}

 
 

T3 买月票

~~我觉得吧,要是你不卡我的dfs,我是绝对可以过的

总之先打代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std; 
typedef long long ll;
char *p1,*p2,buf[1<<20]; 
#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++))) 
//#define GC getchar() 
inline ll in() 
{ 
    ll ans; 
    char t,k; 
    while(((t=GC)!='-'&&(t>'9'||t<'0'))); 
    k=(t=='-'); 
    ans=k?0:(t-'0'); 
    while((t=GC)>='0'&&t<='9')ans=ans*10+t-'0'; 
    return k?-ans:ans; 
}
const int maxn=100010;
const int maxm=200010;
struct edge{
	ll from,to,next,len;
}g[2*maxm];
int head[maxn],cnt=1;
ll dis[4][maxn];
ll dis2[maxn];
ll n,m,s,t,u,v;
void add(ll from,ll to,ll len)
{
	g[++cnt].from=from;
	g[cnt].len=len;
	g[cnt].to=to;
	g[cnt].next=head[from];
	head[from]=cnt;
}
bool mark[maxn];
struct node{
	ll to,dis;
};
bool operator<(node a,node b)
{
	return a.dis>b.dis;
}

void dij1(ll x,ll pos)
{
	priority_queue<node>q;
	memset(mark,0,sizeof(mark));
	memset(dis[pos],0x3f,sizeof(dis[pos]));
	dis[pos][x]=0;
	q.push((node){x,0});
	while(q.size())
	{
		ll u=q.top().to;
		q.pop();
		if(mark[u])continue;
		mark[u]=1;
		for(ll i=head[u];i;i=g[i].next)
		{
			ll v=g[i].to,d=g[i].len;
			if(!mark[v]&&dis[pos][u]+d<dis[pos][v]){
				dis[pos][v]=dis[pos][u]+d;
				q.push((node){v,dis[pos][v]});
			}
		}
	}
}
bool vis[maxn];
ll ans=1e19;
bool if0=0;
ll _min[2][maxn];
node tmp[maxn];
bool cmp(node a,node b){
	return a.dis<b.dis;
}
int main()
{
	ll i,j;
	n=in();m=in();s=in();t=in();u=in();v=in();
	for(i=1;i<=m;i++)
	{
		ll a,b,c;
		a=in();b=in();c=in();
		add(a,b,c);
		add(b,a,c);
	}
	dij1(s,0);
	dij1(t,1);
	dij1(u,2);
	dij1(v,3);
	for(i=1;i<=n;i++)
	{
		_min[0][i]=dis[2][i];
		_min[1][i]=dis[3][i];
		tmp[i]=(node){i,dis[1][i]};
	}
	sort(tmp+1,tmp+1+n,cmp);
	for(i=1;i<=n;i++)
	{
		ll U=tmp[i].to;
		ans=min(ans,min(_min[0][U]+dis[3][U],_min[1][U]+dis[2][U]));
		for(j=head[U];j;j=g[j].next)
		{
			ll V=g[j].to;
			if(dis[1][U]+g[j].len+dis[0][V]==dis[0][t]){
				_min[0][V]=min(_min[0][V],_min[0][U]);
				_min[1][V]=min(_min[1][V],_min[1][U]);
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}

 
 

总结

  1. 一定不要相信样例数据。
  2. 一定不要忘了保存代码。
  3. 一定不要把题想复杂了。
  4. 当你觉得这是道动归时。
  5. 这道题有可能是个贪心。
posted @ 2019-11-06 23:59  国土战略局特工  阅读(125)  评论(0)    收藏  举报