4.10总结

时间非常充裕,但是还是不会T3=_=

开始通读一遍题,然后发现T2非常友善地告诉我们要写最长不降(不升)子序列,而且数据才到2000(小可爱),那么就都跑一边比个大小就行(大约40min)

再看T1与T3,T3要用线段树,就先写个暴力(大概十多分钟?)在去写T1。一开始想的是贪心,先写了两个特判,但很快就发现DFS可行写完用大约30分钟,调试大约十分钟(加了一句边界)。

接下来开始乱搞,试着写了一下树状数组,但是WA掉了(还剩半个多小时),只好去卡常,加快读——结束

T1:

#include<bits/stdc++.h>
using namespace std;
int n,k,ans;
int dfs(int x)
{
	if(n>=x) return n-x;
	if(x%2==1) return min(dfs(x+1)+1,dfs(x-1)+1);
	else return min(dfs(x/2)+1,x-n);
}
int main()
{
	//freopen("catchcow.in","r",stdin);
	//freopen("catchcow.out","w",stdout);
	scanf("%d%d",&n,&k);
	if(n==k)
	{
		printf("0");
		return 0;
	}
	else if(k<n)
	{
		printf("%d",n-k);
		return 0;
	}
	ans=dfs(k);
	printf("%d",ans);
	return 0;
}

不过dfs写最差数据到1e6的题实在是有问题的,这种情况下如果时间充足还是应该用BFS保险

#include<bits/stdc++.h>
using namespace std;
int n,k,vis[1000010];
queue<int>q;
void bfs()
{
	while(1)
	{
		int x=q.front();
		q.pop();
		if(x+1<=1e6&&vis[x+1]==-1)
		{
			vis[x+1]=vis[x]+1;
			q.push(x+1);
		}
		if(x-1<=1e6&&vis[x-1]==-1)
		{
			vis[x-1]=vis[x]+1;
			q.push(x-1);
		}
		if(x*2<=1e6&&vis[x*2]==-1)
		{
			vis[x*2]=vis[x]+1;
			q.push(x*2);
		}
		if(vis[k]!=-1) break;
	}
}
int main()
{
	//freopen("catchcow.in","r",stdin);
	//freopen("catchcow.out","w",stdout);
	memset(vis,-1,sizeof vis);
	scanf("%d%d",&n,&k);
	q.push(n);
	vis[n]=0;
	bfs();
	printf("%d",vis[k]);
	return 0;
}

T2:就裸的最长...子序列,b1,b2 是按升序降序排的原数组

f1[i][j]=min(f1[i][j-1],f1[i-1][j]+abs(a[i]-b1[j]));

f2[i][j]=min(f2[i][j-1],f2[i-1][j]+abs(a[i]-b2[j]));

T3:教主的魔法 

暴力碾标算hhhh回来说正解,emmm就明显线段树,但还是写的不熟练中间卡过的几个地方:第33,41,75,98行,其余都是手误了。还有就是数据与题目不符,其实完全可以if(op=='A') else...

#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
struct node
{
	int min1,max1,flag;
} tree[N*4];
int n,q,a[N],l,r,c;
char ch;
int read()
{
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9')
	{
		if(ch=='-')f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9')
	{
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
void update(int p)
{
	tree[p].max1=max(tree[p<<1].max1,tree[p<<1|1].max1);
	tree[p].min1=min(tree[p<<1].min1,tree[p<<1|1].min1);
}
inline void pushdown(int p)
{
	if(tree[p].flag)
	{
		tree[p<<1].flag+=tree[p].flag;
		tree[p<<1].max1+=tree[p].flag;
		tree[p<<1].min1+=tree[p].flag;
		tree[p<<1|1].flag+=tree[p].flag;
		tree[p<<1|1].max1+=tree[p].flag;
		tree[p<<1|1].min1+=tree[p].flag;
		tree[p].flag=0;
	}
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		tree[p].min1=tree[p].max1=a[l];
		return ;
	}
	int mid=(l+r)/2;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	update(p);
}
void add_edge(int p,int l,int r,int ql,int qr,int c)
{
	if(ql<=l and r<=qr)
	{
		tree[p].max1+=c;
		tree[p].min1+=c;
		tree[p].flag+=c;
		return ;
	}
	pushdown(p);
	int mid=(l+r)/2;
	if(ql<=mid) add_edge(p<<1,l,mid,ql,qr,c);
	if(mid<qr) add_edge(p<<1|1,mid+1,r,ql,qr,c);
	update(p);
}
int qeury(int p,int l,int r,int ql,int qr,int c)
{
	if(ql<=l&&r<=qr&&c<=tree[p].min1) return r-l+1;
	if(ql<=l&&r<=qr&&c>tree[p].max1) return 0;
	pushdown(p);
	int mid=(l+r)/2,ans=0;
	if(ql<=mid) ans+=qeury(p<<1,l,mid,ql,qr,c);
	if(mid<qr) ans+=qeury(p<<1|1,mid+1,r,ql,qr,c);
	update(p);
	return ans;
}
int main()
{
	//freopen("magic.in","r",stdin);
	//freopen("magic.out","w",stdout);
	//std::ios::sync_with_stdio(0);
	n=read();
	q=read();
	for(int i=1; i<=n; ++i) a[i]=read();
	build(1,1,n);
	while(q--)
	{
		cin>>ch;
		l=read();
		r=read();
		c=read();
		if(ch=='M') add_edge(1,1,n,l,r,c);
		else printf("%d\n",qeury(1,1,n,l,r,c));
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiyuping24

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值