CODEFORCE ROUND #625 DIV2

不得不说cf题目都是毒瘤,一篇读下来我头都裂开了 (哭)

个人认为这次的大坑点是E题 不谈有生之年的F题

和平常一样A,B,C都是思维题不过这次C题有坑还是贴一下

C题:

https://codeforces.ml/contest/1321/problem/C

题目大意就是给你n个字母,这个字母能被删除的条件是相邻的字母存在ASCII比他小1,问最多能删几个字母。

这里的坑就是你当前枚举的最高字母要多遍历几遍,如果只遍历一遍那

bbbbbbbb a bbbbb这种样例就会输出a前面一个加后面所有b的个数这样明显不对

刚开始不知道string有erase函数搞得我头皮发麻

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<set>
#include<list>
#include<vector>
#include<string>
using namespace std;
const int N=107;
int n,ans;
string s;
int main()
{
	scanf("%d",&n);
	getchar();
	cin>>s;
	for(int i='z';i>='a';i--)
	{
		for(int k=100;k>=0;k--)//多遍历几次
		{
			for(int j=0;j<s.size();j++)
			{
				if(i==s[j])
				{
					if(s[j]-s[j-1]==1||s[j]-s[j+1]==1)
					{
						ans++;
						s.erase(j,1);
						j--;
					}
				}
			}
		} 
	} 
	printf("%d",ans);
	return 0;
} 

  

D题:

https://codeforces.ml/contest/1321/problem/D

题目大意就是n个点m条单向边,没有重边自环大概 给你一条初始路径(u,v),判断这条路径上的点是否符合最短路径,如果不符合就会重新导航问你最大和最小重新导航的次数比如(u,v)=1,2,3,4有这样一个图

从1到4的最短路是1,5,4而路径会从1到2,不满足最短路就重新导航,2到4的最短路有2, 3, 4,2,6,4两条,若求最大值则系统应显示出264这样从2到3系统就会重新导航一次,如果系统本身显示的是234则从2到3满足路线就不会重新导航(求最小值)

想想最短路的定义,dis i=dis j+w则是i到j的最短路这里判断固定路线z中相邻两点是不是的最短路只需判断dis[a1]?=dis[a2]+1

如果等于:求最小值则ansminn不用加,求最大值则枚举a1的子节点若还存在一条最短路(dis children==dis a2)则ansmaxn++否则ansmaxn不加

如果不想等则肯定要重新导航ansminn,ansmaxn都加

求所有点到终点的最短路要反向建图

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<set>
#include<list>
#include<vector>
#include<string>
#include<queue>
using namespace std;
const int N=2e5+7,inf=0x3f3f3f3f;
int n,m,ansmaxn,ansminn,x,y,k,a[N],dis[N];
bool use[N];
queue < int > q;
vector < int > f1[N],f[N];
void spfa(int x)
{
	for(int i=1;i<=n;i++)
		dis[i]=inf;
	//memset(dis,inf,sizeof(dis));
	dis[x]=0;
	q.push(x);
	while(!q.empty())
	{
		int temp=q.front();
		q.pop();
		use[temp]=0;
		for(int i=0;i<f[temp].size();i++)
		{
			int xx=f[temp][i];
			if(dis[xx]>dis[temp]+1)
			{
				dis[xx]=dis[temp]+1;
				if(use[xx]==0)
				{
					use[xx]=1;
					q.push(xx);
				}
			}
		}
	}
	return ;	
}
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%d %d",&x,&y);
		f[y].push_back(x);//反向建图求dis
		f1[x].push_back(y);//正向建图求子节点
	}
	scanf("%d",&k);
	for(int i=1;i<=k;i++)
		scanf("%d",&a[i]);
	spfa(a[k]);
	/*for(int i=1;i<=n;i++)
	{
		printf("%d ",dis[i]);
	}*/
	for(int i=1;i<k;i++)
	{
		if(dis[a[i]]==dis[a[i+1]]+1)
		{
			for(int j=0;j<f1[a[i]].size();j++)//枚举子节点
			{
				int temp=f1[a[i]][j];
				if(dis[temp]==dis[a[i+1]]&&temp!=a[i+1])
				{
					ansmaxn++;
					break;
				}
			}
		}
		else
		{
			ansmaxn++;
			ansminn++;
		}
	}
	printf("%d %d",ansminn,ansmaxn);
	return 0;
} 

  

E题:

这题坑我快5个小时

现在过了我只想默默说一句 f**k

题目大意是输入n,m,p有n个攻击装备,m个防御装备,p个怪物每个怪物被打败后都会有钱并且怪物每个只能打一次

攻击装备和防御装备各买一个(即使怪物得到的钱很少也要买),且装备都有两个值 attack ,cost

能打败怪物的条件是n attack>p def && m defense>p atk注意怪物是先输入def再是atk而装备相反。

求获得的利润最大值 打败怪物获得的钱-装备花费的钱

后来才知道这样的东西叫 二维偏序  听说624的F题也是这个?!!

就是先将一维x放进线段树维护,另一维y排序,然后根据枚举的y ask线段树得出答案

这种代码是用一种特殊的方式排序,后来直接o1查询 值得借鉴

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<set>
#include<list>
#include<vector>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
const int N=2e5+7,M=1e6+5;
const long long inf=0xfffffffff;
int n,m,p;
long long ca[M+5],cb[M+5],acost,bcost,a[N],b[N],ans=-inf;
//ca,cb数组小心越界 
struct node 
{
	long long at,w,def;//atk==x装备的def==x 
	bool operator <(const node &t)const{return def<t.def;}
}c[N];
struct node3
{
	long long sum,maxn,add;
}t[M*4];
long long max(long long x,long long y)
{
	if(x>y)
		return x;
	return y;
}
void built(int p,int l,int r)
{
	t[p].add=0;
	if(l==r)
	{
		t[p].maxn=-cb[l];
		//t[p].sum=-b[l].w;
		return ;
	}
	int mid=(l+r)/2;
	built(p*2,l,mid);
	built(p*2+1,mid+1,r);
	t[p].maxn=max(t[p*2].maxn,t[p*2+1].maxn);
	//t[p].sum=t[p*2].sum+t[p*2+1].sum;
}
void push_tag(int p,int l,int r)
{
	if(t[p].add)
	{
		t[p*2].add+=t[p].add;
		t[p*2+1].add+=t[p].add;
		t[p*2].maxn+=t[p].add;
		t[p*2+1].maxn+=t[p].add;
		t[p].add=0;
	}
	return ;
}
void push_down(int p)
{
	t[p].maxn=max(t[p*2].maxn,t[p*2+1].maxn);
}
void up(int p,int qx,int zx,int gl,int gr,int k)//区间加操作 
{
	if(qx>=gl&&zx<=gr)
	{
		t[p].add+=k;
		t[p].maxn+=k;
		return ;
	}
	int mid=(qx+zx)/2;
	push_tag(p,qx,zx);
	if(gl<=mid)
		up(p*2,qx,mid,gl,gr,k);
	if(gr>mid)
		up(p*2+1,mid+1,zx,gl,gr,k);
	push_down(p);
	return ;
}

long long askmaxn(int p,int qx,int zx,int gl,int gr)//查询最大值 
{
	if(qx>=gl&&zx<=gr)
	{
		return t[p].maxn;
	}
	int mid=(qx+zx)/2;
	long long ans=-inf;
	push_tag(p,qx,zx);
	if(gl<=mid)	
		ans=max(ans,askmaxn(p*2,qx,mid,gl,gr));
	if(gr>mid)
		ans=max(ans,askmaxn(p*2+1,mid+1,zx,gl,gr));
	return ans;
}
int main()
{
	scanf("%d %d %d",&n,&m,&p);
	for(int i=1;i<=M+1;i++)
	{
		ca[i]=inf;//攻击为i时所要的最小的钱 
		cb[i]=inf;//防御为i时所要的最小的钱 
	}
	for(int i=1;i<=n;i++)
	{	
		scanf("%lld %lld",&a[i],&acost);
		ca[a[i]]=min(ca[a[i]],acost); 
	} 
	for(int i=1;i<=m;i++)
	{
		scanf("%lld %lld",&b[i],&bcost);
		cb[b[i]]=min(cb[b[i]],bcost);
	}
	for(int i=M;i>=1;i--)
	{
		ca[i]=min(ca[i],ca[i+1]);
		cb[i]=min(cb[i],cb[i+1]);//如果防御力为i存在铠甲则有i-1防御力铠甲的代价最小仍为cb[i] 
	}
	built(1,1,M);//防御力线段树 
	for(int i=1;i<=p;i++)
		scanf("%lld %lld %lld",&c[i].def,&c[i].at,&c[i].w);
	sort(c+1,c+p+1);//monster 防御力从小到大 
	ans=-ca[1]-cb[1];
	//printf("%lld %lld\n",ca[1],cb[1]);
	for(int i=1;i<=p;i++)
	{
		up(1,1,M,c[i].at+1,M,c[i].w); 
		//先假设剑的攻击力都足以破防,则防御力大于等于c[i].at+1的装备全部可以得到c[i].w的钱
		ans=max(ans,askmaxn(1,1,M,1,M)-ca[c[i].def+1]); 
		//防御力已经满足则只需要减去攻击力大于等于c[i].def+1的购买费用即可 
		//因为防御力已经排序了,所有后来的monster防御力一定大于先前的
		//当前选择的剑攻击力一定能破之前怪的防此时满足up的假设 故up函数成立 
	}
	printf("%lld",ans);
	return 0;
} 

  

这种是我最开始写的,因为inf 是int 类型(和上面代码开始犯的错一样)没过我还以为思路或者线段树写错了...结果没错

就是这个const long long inf=0xfffffffff坑死个人

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<set>
#include<list>
#include<vector>
#include<string>
#include<queue>
#include<algorithm>
using namespace std;
const int N=2e5+7;
const long long inf=0xfffffffff;
int n,m,p,pos1,pos2,pos3;
long long mat[N],mde[N],mv[N],de[N],ans=-inf;
bool use[N];
struct node 
{
	long long x,w,def;//atk==x?????def==x 
	bool operator <(const node &t)const{return x<t.x;}
}a[N],b[N],c[N];
struct node3
{
	long long sum,maxn,add;
}t[N*4];
long long max(long long x,long long y)
{
	if(x>y)
		return x;
	return y;
}
void built(int p,int l,int r)
{
	t[p].add=0;
	if(l==r)
	{
		t[p].maxn=-a[l].w;
		//t[p].sum=-b[l].w;
		return ;
	}
	int mid=(l+r)/2;
	built(p*2,l,mid);
	built(p*2+1,mid+1,r);
	t[p].maxn=max(t[p*2].maxn,t[p*2+1].maxn);
	//t[p].sum=t[p*2].sum+t[p*2+1].sum;
}
void push_tag(int p,int l,int r)
{
	if(t[p].add)
	{
		t[p*2].add+=t[p].add;
		t[p*2+1].add+=t[p].add;
		t[p*2].maxn+=t[p].add;
		t[p*2+1].maxn+=t[p].add;
		t[p].add=0;
	}
	return ;
}
void push_down(int p)
{
	t[p].maxn=max(t[p*2].maxn,t[p*2+1].maxn);
}
void up(int p,int qx,int zx,int gl,int gr,int k) 
{
	if(qx>=gl&&zx<=gr)
	{
		t[p].add+=k;
		t[p].maxn+=k;
		return ;
	}
	int mid=(qx+zx)/2;
	push_tag(p,qx,zx);
	if(gl<=mid)
		up(p*2,qx,mid,gl,gr,k);
	if(gr>mid)
		up(p*2+1,mid+1,zx,gl,gr,k);
	push_down(p);
	return ;
}
 
long long askmaxn(int p,int qx,int zx,int gl,int gr)
{
	if(qx>=gl&&zx<=gr)
	{
		return t[p].maxn;
	}
	int mid=(qx+zx)/2;
	long long ans=-inf;
	if(gl<=mid)	
		ans=max(ans,askmaxn(p*2,qx,mid,gl,gr));
	if(gr>mid)
		ans=max(ans,askmaxn(p*2+1,mid+1,zx,gl,gr));
	return ans;
}
int main()
{
	scanf("%d %d %d",&n,&m,&p);
	for(int i=1;i<=n;i++)
		scanf("%lld %lld",&a[i].x,&a[i].w);
	for(int i=1;i<=m;i++)
		scanf("%lld %lld",&b[i].x,&b[i].w);
	for(int i=1;i<=p;i++)
		scanf("%lld %lld %lld",&c[i].def,&c[i].x,&c[i].w);
	sort(a+1,a+n+1);
	sort(b+1,b+m+1);
	sort(c+1,c+p+1);
	for(int i=1;i<=p;i++)
	{
		mat[i]=c[i].x;
		mv[i]=c[i].w;
		mde[i]=c[i].def;
	}
	for(int i=1;i<=n;i++)
		de[i]=a[i].x; 
	built(1,1,n);
	for(int i=1;i<=m;i++)
	{
		if(b[i].x>mat[p])
			pos2=p;
		else
			pos2=lower_bound(mat+1,mat+p+1,b[i].x)-mat-1;
		for(int j=pos1+1;j<=pos2;j++)
		{
			//printf("#@$%d %d ",de[n],mde[j]);
			if(de[n]<=mde[j])
				continue;
			else
				pos3=upper_bound(de+1,de+n+1,mde[j])-de;
			//printf("pos3=%d ", pos3);
			up(1,1,n,pos3,n,mv[j]);
			pos1=pos2;
		}
		ans=max(ans,askmaxn(1,1,n,1,n)-b[i].w);
		//printf("%lld ",askmaxn(1,1,n,1,n));
	}
	printf("%lld",ans);
	return 0;
} 

E题已经让我憔悴不堪,F题有生之年吧 

posted @ 2020-03-02 23:55  Sakura_Momoko  阅读(289)  评论(0编辑  收藏  举报