牛客小白月赛24题解 A-J

A最短路  几何

大佬几何模板

求出sum角,

求A,B 角, C角

得直线A-D1  直线B-D2  弧线D1-D2  相加即可

#include<bits/stdc++.h> 
using namespace std;
// `计算几何模板`
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x){
	if(fabs(x) < eps)return 0;
	if(x < 0)return -1;
	else return 1;
}
//square of a double
inline double sqr(double x){return x*x;}

struct Point{
	double x,y;
	Point(){}
	Point(double _x,double _y){
		x = _x;
		y = _y;
	}
	void input(){
		scanf("%lf%lf",&x,&y);
	}
	void output(){
		printf("%.2f %.2f\n",x,y);
	}
	bool operator == (Point b)const{
		return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
	}
	bool operator < (Point b)const{
		return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
	}
	Point operator -(const Point &b)const{
		return Point(x-b.x,y-b.y);
	}
	//叉积
	double operator ^(const Point &b)const{
		return x*b.y - y*b.x;
	}
	//点积
	double operator *(const Point &b)const{
		return x*b.x + y*b.y;
	}
	//返回长度
	double len(){
		return hypot(x,y);//库函数
	}
	//返回长度的平方
	double len2(){
		return x*x + y*y;
	}
	//返回两点的距离
	double distance(Point p){
		return hypot(x-p.x,y-p.y);
	}
	Point operator +(const Point &b)const{
		return Point(x+b.x,y+b.y);
	}
	Point operator *(const double &k)const{
		return Point(x*k,y*k);
	}
	Point operator /(const double &k)const{
		return Point(x/k,y/k);
	}
	//`计算pa  和  pb 的夹角`
	//`就是求这个点看a,b 所成的夹角`
	//`测试 LightOJ1203`
	double rad(Point a,Point b){
		Point p = *this;
		return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
	}
	//`化为长度为r的向量`
	Point trunc(double r){
		double l = len();
		if(!sgn(l))return *this;
		r /= l;
		return Point(x*r,y*r);
	}
	//`逆时针旋转90度`
	Point rotleft(){
		return Point(-y,x);
	}
	//`顺时针旋转90度`
	Point rotright(){
		return Point(y,-x);
	}
	//`绕着p点逆时针旋转angle`
	Point rotate(Point p,double angle){
		Point v = (*this) - p;
		double c = cos(angle), s = sin(angle);
		return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
	}
};

struct Line{
	Point s,e;
	Line(){}
	Line(Point _s,Point _e){
		s = _s;
		e = _e;
	}
	bool operator ==(Line v){
		return (s == v.s)&&(e == v.e);
	}
	//`根据一个点和倾斜角angle确定直线,0<=angle<pi`
	Line(Point p,double angle){
		s = p;
		if(sgn(angle-pi/2) == 0){
			e = (s + Point(0,1));
		}
		else{
			e = (s + Point(1,tan(angle)));
		}
	}
	//ax+by+c=0
	Line(double a,double b,double c){
		if(sgn(a) == 0){
			s = Point(0,-c/b);
			e = Point(1,-c/b);
		}
		else if(sgn(b) == 0){
			s = Point(-c/a,0);
			e = Point(-c/a,1);
		}
		else{
			s = Point(0,-c/b);
			e = Point(1,(-c-a)/b);
		}
	}
	void input(){
		s.input();
		e.input();
	}
	void adjust(){
		if(e < s)swap(s,e);
	}
	//求线段长度
	double length(){
		return s.distance(e);
	}
	//`返回直线倾斜角 0<=angle<pi`
	double angle(){
		double k = atan2(e.y-s.y,e.x-s.x);
		if(sgn(k) < 0)k += pi;
		if(sgn(k-pi) == 0)k -= pi;
		return k;
	}
	//`点和直线关系`
	//`1  在左侧`
	//`2  在右侧`
	//`3  在直线上`
	int relation(Point p){
		int c = sgn((p-s)^(e-s));
		if(c < 0)return 1;
		else if(c > 0)return 2;
		else return 3;
	}
	// 点在线段上的判断
	bool pointonseg(Point p){
		return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0;
	}
	//`两向量平行(对应直线平行或重合)`
	bool parallel(Line v){
		return sgn((e-s)^(v.e-v.s)) == 0;
	}
	//`两线段相交判断`
	//`2 规范相交`
	//`1 非规范相交`
	//`0 不相交`
	int segcrossseg(Line v){
		int d1 = sgn((e-s)^(v.s-s));
		int d2 = sgn((e-s)^(v.e-s));
		int d3 = sgn((v.e-v.s)^(s-v.s));
		int d4 = sgn((v.e-v.s)^(e-v.s));
		if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;
		return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||
			(d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||
			(d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||
			(d4==0 && sgn((e-v.s)*(e-v.e))<=0);
	}
	//`直线和线段相交判断`
	//`-*this line   -v seg`
	//`2 规范相交`
	//`1 非规范相交`
	//`0 不相交`
	int linecrossseg(Line v){
		int d1 = sgn((e-s)^(v.s-s));
		int d2 = sgn((e-s)^(v.e-s));
		if((d1^d2)==-2) return 2;
		return (d1==0||d2==0);
	}
	//`两直线关系`
	//`0 平行`
	//`1 重合`
	//`2 相交`
	int linecrossline(Line v){
		if((*this).parallel(v))
			return v.relation(s)==3;
		return 2;
	}
	//`求两直线的交点`
	//`要保证两直线不平行或重合`
	Point crosspoint(Line v){
		double a1 = (v.e-v.s)^(s-v.s);
		double a2 = (v.e-v.s)^(e-v.s);
		return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
	}
	//点到直线的距离
	double dispointtoline(Point p){
		return fabs((p-s)^(e-s))/length();
	}
	//点到线段的距离
	double dispointtoseg(Point p){
		if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)
			return min(p.distance(s),p.distance(e));
		return dispointtoline(p);
	}
	//`返回线段到线段的距离`
	//`前提是两线段不相交,相交距离就是0了`
	double dissegtoseg(Line v){
		return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
	}
	//`返回点p在直线上的投影`
	Point lineprog(Point p){
		return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
	}
	//`返回点p关于直线的对称点`
	Point symmetrypoint(Point p){
		Point q = lineprog(p);
		return Point(2*q.x-p.x,2*q.y-p.y);
	}
};
//圆
struct circle{
	Point p;//圆心
	double r;//半径
	circle(){}
	circle(Point _p,double _r){
		p = _p;
		r = _r;
	}
	circle(double x,double y,double _r){
		p = Point(x,y);
		r = _r;
	}
	//`三角形的外接圆`
	//`需要Point的+ /  rotate()  以及Line的crosspoint()`
	//`利用两条边的中垂线得到圆心`
	//`测试:UVA12304`
	circle(Point a,Point b,Point c){
		Line u = Line((a+b)/2,((a+b)/2)+((b-a).rotleft()));
		Line v = Line((b+c)/2,((b+c)/2)+((c-b).rotleft()));
		p = u.crosspoint(v);
		r = p.distance(a);
	}
	//`三角形的内切圆`
	//`参数bool t没有作用,只是为了和上面外接圆函数区别`
	//`测试:UVA12304`
	circle(Point a,Point b,Point c,bool t){
		Line u,v;
		double m = atan2(b.y-a.y,b.x-a.x), n = atan2(c.y-a.y,c.x-a.x);
		u.s = a;
		u.e = u.s + Point(cos((n+m)/2),sin((n+m)/2));
		v.s = b;
		m = atan2(a.y-b.y,a.x-b.x) , n = atan2(c.y-b.y,c.x-b.x);
		v.e = v.s + Point(cos((n+m)/2),sin((n+m)/2));
		p = u.crosspoint(v);
		r = Line(a,b).dispointtoseg(p);
	}
	//输入
	void input(){
		p.input();
		scanf("%lf",&r);
	}
	//输出
	void output(){
		printf("%.2lf %.2lf %.2lf\n",p.x,p.y,r);
	}
	bool operator == (circle v){
		return (p==v.p) && sgn(r-v.r)==0;
	}
	bool operator < (circle v)const{
		return ((p<v.p)||((p==v.p)&&sgn(r-v.r)<0));
	}
	//面积
	double area(){
		return pi*r*r;
	}
	//周长
	double circumference(){
		return 2*pi*r;
	}
	//`点和圆的关系`
	//`0 圆外`
	//`1 圆上`
	//`2 圆内`
	int relation(Point b){
		double dst = b.distance(p);
		if(sgn(dst-r) < 0)return 2;
		else if(sgn(dst-r)==0)return 1;
		return 0;
	}
	//`线段和圆的关系`
	//`比较的是圆心到线段的距离和半径的关系`
	// 0 不相交
	// 1 相切
	// 2 相交 
	int relationseg(Line v){
		double dst = v.dispointtoseg(p);
		if(sgn(dst-r) < 0)return 2;//相交 
		else if(sgn(dst-r) == 0)return 1;
		return 0;
	}
	//`直线和圆的关系`
	//`比较的是圆心到直线的距离和半径的关系`
	int relationline(Line v){
		double dst = v.dispointtoline(p);
		if(sgn(dst-r) < 0)return 2;
		else if(sgn(dst-r) == 0)return 1;
		return 0;
	}
	//`两圆的关系`
	//`5 相离`
	//`4 外切`
	//`3 相交`
	//`2 内切`
	//`1 内含`
	//`需要Point的distance`
	//`测试:UVA12304`
	int relationcircle(circle v){
		double d = p.distance(v.p);
		if(sgn(d-r-v.r) > 0)return 5;
		if(sgn(d-r-v.r) == 0)return 4;
		double l = fabs(r-v.r);
		if(sgn(d-r-v.r)<0 && sgn(d-l)>0)return 3;
		if(sgn(d-l)==0)return 2;
		if(sgn(d-l)<0)return 1;
	}
	//`求两个圆的交点,返回0表示没有交点,返回1是一个交点,2是两个交点`
	//`需要relationcircle`
	//`测试:UVA12304`
	int pointcrosscircle(circle v,Point &p1,Point &p2){
		int rel = relationcircle(v);
		if(rel == 1 || rel == 5)return 0;
		double d = p.distance(v.p);
		double l = (d*d+r*r-v.r*v.r)/(2*d);
		double h = sqrt(r*r-l*l);
		Point tmp = p + (v.p-p).trunc(l);
		p1 = tmp + ((v.p-p).rotleft().trunc(h));
		p2 = tmp + ((v.p-p).rotright().trunc(h));
		if(rel == 2 || rel == 4)
			return 1;
		return 2;
	}
	//`求直线和圆的交点,返回交点个数`
	int pointcrossline(Line v,Point &p1,Point &p2){
		if(!(*this).relationline(v))return 0;
		Point a = v.lineprog(p);
		double d = v.dispointtoline(p);
		d = sqrt(r*r-d*d);
		if(sgn(d) == 0){
			p1 = a;
			p2 = a;
			return 1;
		}
		p1 = a + (v.e-v.s).trunc(d);
		p2 = a - (v.e-v.s).trunc(d);
		return 2;
	}
	//`得到过a,b两点,半径为r1的两个圆`
	int gercircle(Point a,Point b,double r1,circle &c1,circle &c2){
		circle x(a,r1),y(b,r1);
		int t = x.pointcrosscircle(y,c1.p,c2.p);
		if(!t)return 0;
		c1.r = c2.r = r;
		return t;
	}
	//`得到与直线u相切,过点q,半径为r1的圆`
	//`测试:UVA12304`
	int getcircle(Line u,Point q,double r1,circle &c1,circle &c2){
		double dis = u.dispointtoline(q);
		if(sgn(dis-r1*2)>0)return 0;
		if(sgn(dis) == 0){
			c1.p = q + ((u.e-u.s).rotleft().trunc(r1));
			c2.p = q + ((u.e-u.s).rotright().trunc(r1));
			c1.r = c2.r = r1;
			return 2;
		}
		Line u1 = Line((u.s + (u.e-u.s).rotleft().trunc(r1)),(u.e + (u.e-u.s).rotleft().trunc(r1)));
		Line u2 = Line((u.s + (u.e-u.s).rotright().trunc(r1)),(u.e + (u.e-u.s).rotright().trunc(r1)));
		circle cc = circle(q,r1);
		Point p1,p2;
		if(!cc.pointcrossline(u1,p1,p2))cc.pointcrossline(u2,p1,p2);
		c1 = circle(p1,r1);
		if(p1 == p2){
			c2 = c1;
			return 1;
		}
		c2 = circle(p2,r1);
		return 2;
	}
	//`同时与直线u,v相切,半径为r1的圆`
	//`测试:UVA12304`
	int getcircle(Line u,Line v,double r1,circle &c1,circle &c2,circle &c3,circle &c4){
		if(u.parallel(v))return 0;//两直线平行
		Line u1 = Line(u.s + (u.e-u.s).rotleft().trunc(r1),u.e + (u.e-u.s).rotleft().trunc(r1));
		Line u2 = Line(u.s + (u.e-u.s).rotright().trunc(r1),u.e + (u.e-u.s).rotright().trunc(r1));
		Line v1 = Line(v.s + (v.e-v.s).rotleft().trunc(r1),v.e + (v.e-v.s).rotleft().trunc(r1));
		Line v2 = Line(v.s + (v.e-v.s).rotright().trunc(r1),v.e + (v.e-v.s).rotright().trunc(r1));
		c1.r = c2.r = c3.r = c4.r = r1;
		c1.p = u1.crosspoint(v1);
		c2.p = u1.crosspoint(v2);
		c3.p = u2.crosspoint(v1);
		c4.p = u2.crosspoint(v2);
		return 4;
	}
	//`同时与不相交圆cx,cy相切,半径为r1的圆`
	//`测试:UVA12304`
	int getcircle(circle cx,circle cy,double r1,circle &c1,circle &c2){
		circle x(cx.p,r1+cx.r),y(cy.p,r1+cy.r);
		int t = x.pointcrosscircle(y,c1.p,c2.p);
		if(!t)return 0;
		c1.r = c2.r = r1;
		return t;
	}

	//`过一点作圆的切线(先判断点和圆的关系)`
	//`测试:UVA12304`
	int tangentline(Point q,Line &u,Line &v){
		int x = relation(q);
		if(x == 2)return 0;
		if(x == 1){
			u = Line(q,q + (q-p).rotleft());
			v = u;
			return 1;
		}
		double d = p.distance(q);
		double l = r*r/d;
		double h = sqrt(r*r-l*l);
		u = Line(q,p + ((q-p).trunc(l) + (q-p).rotleft().trunc(h)));
		v = Line(q,p + ((q-p).trunc(l) + (q-p).rotright().trunc(h)));
		return 2;
	}
	//`求两圆相交的面积`
	double areacircle(circle v){
		int rel = relationcircle(v);
		if(rel >= 4)return 0.0;
		if(rel <= 2)return min(area(),v.area());
		double d = p.distance(v.p);
		double hf = (r+v.r+d)/2.0;
		double ss = 2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d));
		double a1 = acos((r*r+d*d-v.r*v.r)/(2.0*r*d));
		a1 = a1*r*r;
		double a2 = acos((v.r*v.r+d*d-r*r)/(2.0*v.r*d));
		a2 = a2*v.r*v.r;
		return a1+a2-ss;
	}
	//`求圆和三角形pab的相交面积`
	//`测试:POJ3675 HDU3982 HDU2892`
	double areatriangle(Point a,Point b){
		if(sgn((p-a)^(p-b)) == 0)return 0.0;
		Point q[5];
		int len = 0;
		q[len++] = a;
		Line l(a,b);
		Point p1,p2;
		if(pointcrossline(l,q[1],q[2])==2){
			if(sgn((a-q[1])*(b-q[1]))<0)q[len++] = q[1];
			if(sgn((a-q[2])*(b-q[2]))<0)q[len++] = q[2];
		}
		q[len++] = b;
		if(len == 4 && sgn((q[0]-q[1])*(q[2]-q[1]))>0)swap(q[1],q[2]);
		double res = 0;
		for(int i = 0;i < len-1;i++){
			if(relation(q[i])==0||relation(q[i+1])==0){
				double arg = p.rad(q[i],q[i+1]);
				res += r*r*arg/2.0;
			}
			else{
				res += fabs((q[i]-p)^(q[i+1]-p))/2.0;
			}
		}
		return res;
	}
};

Point a,b;
circle c;
Line l;
int main() 
{
	a.input();
	b.input();
	c.input();
	l=Line(a,b);
	if(c.relationseg(l)!=2)
	{
		printf("%.6lf\n",l.length());
	}
	else 
	{
		double A=acos(c.r/a.distance(c.p));
		double B=acos(c.r/b.distance(c.p));		
		double sum=c.p.rad(a,b);
		double C=sum-A-B;
		double ans=0;
		double la,lb;
		la=a.distance(c.p);
		lb=b.distance(c.p);
		ans+=la*sin(A);
		ans+=lb*sin(B) ;
		ans+=c.r*C;
		printf("%.6lf\n",ans);
	}
}

B 组队  

排序,枚举队伍最小值然后二分求出该情况下的队伍人数,即可

#include<bits/stdc++.h>
using namespace std;
int T;
int n,m;
int a[200005];
int main()
{
    scanf("%d",&T)  ;
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        sort(a,a+n);
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int dd=upper_bound(a,a+n,a[i]+m)-a;
            ans=max(ans,dd-i);
        }
        printf("%d\n",ans);
    }
}

C 十面埋伏

DFS暴力即可

#include<bits/stdc++.h> 
#define pai pair<int,int> 
using namespace std;
int n,m;
char a[505][505];
int b[505][505];
int main()
{
	scanf("%d%d",&n,&m);
	memset(a,'.',sizeof(a));
	for(int i=1;i<=n;i++)
	{
		scanf("%s",a[i]+1);
	}
	queue<pai> p;
	p.push(pai(0,0));
	while(p.size())//BFS 对外围'.' 染色 
	{
		
		pai P=p.front();
		p.pop();
		int i=P.first;
		int j=P.second;
		int aa[4]={-1,0,1,0};
		int bb[4]={0,-1,0,1};
		for(int k=0;k<4;k++)
		{
			int ii=i+aa[k];
			int jj=j+bb[k];
			if(ii>=0&&jj>=0&&ii<=n&&jj<=m&&a[ii][jj]=='.'&&b[ii][jj]==0)
			{
				b[ii][jj]=1;
				p.push(pai(ii,jj));
			}
		}
	}
	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(a[i][j]=='#')//暴力改成 '*' 
			{
				if(a[i-1][j]=='.') a[i-1][j]='*';
				if(a[i][j-1]=='.') a[i][j-1]='*';
				if(a[i+1][j]=='.') a[i+1][j]='*';
				if(a[i][j+1]=='.') a[i][j+1]='*';
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(a[i][j]=='*')
			{				
			 if(b[i][j])a[i][j]='*';
			 else a[i][j]='.'; //敌人内部不需要士兵 
			}
			
		}
	}
	for(int i=1;i<=n;i++)
	{
		printf("%s\n",a[i]+1);
	}
}

D 牛妹吃豆子

二维差分例题

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,k,q;
ll a[2003][2003];
int main()
{
	scanf("%d%d%d%d",&n,&m,&k,&q);
	for(int i=0;i<k;i++)
	{
		int x1,x2,y1,y2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		a[x1][y1]++;
		a[x1][y2+1]--;
		a[x2+1][y1]--;
		a[x2+1][y2+1]++;
	}
	for(int i=1;i<=n;i++)//差分 
	{
		for(int j=1;j<=m;j++)
		{
			a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
		}
	}
	for(int i=1;i<=n;i++)//区块和 
	{
		for(int j=1;j<=m;j++)
		{
			a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
		}
	}
	for(int i=0;i<q;i++)
	{
		int x1,x2,y1,y2;
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		printf("%lld\n",a[x2][y2]-a[x1-1][y2]-a[x2][y1-1]+a[x1-1][y1-1]);
	}
}

E 旅旅旅游

3次最短路
1.数组D[i] 求1起点到 i 的最短路

2.数组d[i] 求n 起点到 i 的最短路

枚举每条边 u v c

若满足 d[u]+D[v]+c==D[n]||d[v]+D[u]+c==D[n] 则在最短路径上,忽略

若不满足 加入GG边集,重新建图

3. 再次 ,数组D[i] 求1起点到 i 的最短路

枚举每个城市,若D[i] ==inf 说明不存在路径可达 非法 输出NO

#include<bits/stdc++.h>
#define pai pair<int,int> 
#define ll long long
using namespace std;

int n,m;
vector<pai> G[100005],g[100005];
struct node
{
	int u,v,c;
}N[500005];
ll D[100005],d[100005];
void dij1()
{
	priority_queue<pai,vector<pai>,greater<pai> > q;
	D[1]=0;
	q.push(pai(0,1));
	while(q.size())
	{		
		pai P=q.top();
		q.pop();
		int F=P.first,S=P.second;
		if(F>D[S]) continue;
		for(auto T:G[S])
		{		 
			if(T.first+D[S]<D[T.second])
			{
				D[T.second]=T.first+D[S];
				q.push(pai(D[T.second],T.second)) ;
			}
		}
	}
}

void dij2()
{
	priority_queue<pai,vector<pai>,greater<pai> > q;
	d[n]=0;
	q.push(pai(0,n));
	while(q.size())
	{		
		pai P=q.top();
		q.pop();
		int F=P.first,S=P.second;
		if(F>d[S]) continue;
		for(auto T:G[S])
		{		 
			if(T.first+d[S]<d[T.second])
			{
				d[T.second]=T.first+d[S];
				q.push(pai(d[T.second],T.second)) ;
			}
		}
	}
}

void dij3()
{
	priority_queue<pai,vector<pai>,greater<pai> > q;
	D[1]=0;
	q.push(pai(0,1));
	while(q.size())
	{		
		pai P=q.top();
		q.pop();
		int F=P.first,S=P.second;
		if(F>D[S]) continue;
		for(auto T:g[S])
		{		 
			if(T.first+D[S]<D[T.second])
			{
				D[T.second]=T.first+D[S];
				q.push(pai(D[T.second],T.second)) ;
			}
		}
	}
}
int v[500005];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int u,v,c;
		scanf("%d%d%d",&u,&v,&c);
		G[u].push_back(pai(c,v));
		G[v].push_back(pai(c,u));
		N[i].u=u;
		N[i].v=v;
		N[i].c=c;
	}
	for(int i=0;i<=n;i++)
	{
		D[i]=1e18;
		d[i]=1e18;
	}	
	dij1();
	dij2();	
	
	for(int i=1;i<=m;i++)
	{
		int u=N[i].u;
		int v=N[i].v;
		int c=N[i].c;
		if(d[u]+D[v]+c==D[n]||d[v]+D[u]+c==D[n])
		{
			continue;
		}
		else
		{
			g[u].push_back(pai(c,v));
			g[v].push_back(pai(c,u));			
		} 
	}	
	for(int i=0;i<=n;i++)
	{
		D[i]=1e18;
		d[i]=1e18;
	}
	dij3();
	int flag=0;
	for(int i=1;i<=n;i++)
	{
		if(D[i]==1e18)//不能到达 
		{
			flag=1;
			break;
		}
	}
	if(flag) puts("NO");
	else puts("YES");
	
	
	
}

F 斗兽棋

每个动物编号 

if(牛妹赢 ) puts("tiangou txdy");

else puts("tiangou yiwusuoyou");

#include<bits/stdc++.h>
using namespace std;
char s[20],ss[20];
int main()
{
	map<char,int> mp;
	mp['e']=0;
	mp['t']=1;
	mp['c']=2;
	mp['m']=3;
	scanf("%s %s",s,ss);
	int a=mp[s[0]];
	int b=mp[ss[0]];
	if((b+1)%4==a) puts("tiangou txdy");
	else puts("tiangou yiwusuoyou");
	
}

G 做题

排序,贪心  注意long long 

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
ll n;
long long m;
ll a[500005];
int main()
{
	scanf("%lld%lld",&n,&m);
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&a[i]);
	}
	sort(a,a+n);
	ll num=0;
	long long sum=0;
	for(int i=0;sum+a[i]<=m&&i<n;i++)
	{		
			sum+=a[i];
			num++;
	}
	printf("%lld\n",num);
}

H 人人都是好朋友

每个下手用map 取1~num 编号 ,离散化

并查集 即可

#include<bits/stdc++.h>
using namespace std;
int f[2000006],dep[1000006];
struct node
{
	int a,b,c;
}N[1000006];

int find(int x)
{
	if(f[x]==x) return x;
	else f[x]=find(f[x]);
}
void uin(int x,int y)
{	
	int fx=find(x);
	int fy=find(y);
	if(fx==fy) return ;
	if(dep[fx]<dep[fy])
	{
		f[fx]=fy;
	}
	else 
	{
		f[fy]=fx;
		if(dep[fy]==dep[fx]) dep[fx]++;
	}
	
}
int T,n;

int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
unordered_map<int,int> fa;
		int num=1;
		for(int i=0;i<n;i++)
		{
			scanf("%d%d%d",&N[i].a,&N[i].b,&N[i].c) ;
		
				if(fa[N[i].a]==0) fa[N[i].a]=num++;
				if(fa[N[i].b]==0) fa[N[i].b]=num++;			
		}
		
		for(int i=0;i<n;i++)
		{
			N[i].a=fa[N[i].a];
			N[i].b=fa[N[i].b];
		}
		
		for(int i=1;i<num;i++)
		{
			dep[i]	=0;
		 f[i]=i;
		}
		for(int i=0;i<n;i++)
		{
			if(N[i].c)
			{
				uin(N[i].a,N[i].b);
			}

		}
		int flag=0;
		for(int i=0;i<n;i++)
		{
			if(N[i].c==0)
			{
				if(find(N[i].a)==find(N[i].b))
				{
					flag=1;
					break;
				}
			}
		}
		if(!flag) puts("YES");
		else puts("NO") ;
	}
		
}

I 求和

求每个节点dfs序 保存每个节点子树的dfs序范围 L[i],R[i]

建立线段树,即可

自省:

up(1,1,n,L[a],x)   !!!

NO  up(1,1,4000006,L[a],x)  

 

#include<bits/stdc++.h>
#define ll long long
#define ls o*2
#define rs o*2+1 
#define mid (l+r)/2
using namespace std;
int n,m,k;
ll tree[8000006];
vector<int> G[1000006];
ll v[1000006];
int L[1000006];
int R[1000006];
int cnt=0;
void  dfs(int a,int fa)
{
	L[a]=++cnt;
	for(auto P:G[a])
	{
		if(P==fa) continue;
		dfs(P,a);
	}
	R[a]=cnt;
}
void  up(int o,int l,int r,int p,ll v)
{
	if(l==r)
	{
		tree[o]+=v;
		return ;
	}
		
	if(p<=mid) up(ls,l,mid,p,v);
	else up(rs,mid+1,r,p,v);
	tree[o]=tree[ls]+tree[rs];
}

ll qu(int o,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr)
	{
		return tree[o];
	}
	ll sum=0;
	if(ql<=mid) sum+=qu(ls,l,mid,ql,qr);
	if(mid+1<=qr) sum+=qu(rs,mid+1,r,ql,qr);
	return sum;
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&v[i]);
	}
	for(int i=0;i<n-1;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(k,0);

	for(int i=1;i<=n;i++)
	{
		up(1,1,n,L[i],v[i]);
	}
	
	for(int i=0;i<m;i++)
	{
		int X;
		scanf("%d",&X);
		if(X==1)
		{
			int a;
			ll x;
			scanf("%d%lld",&a,&x);
			up(1,1,n,L[a],x);
		}
		else 
		{
			int a;
			scanf("%d",&a);
			printf("%lld\n",qu(1,1,n,L[a],R[a]));
		}
	}
	
}

J 建设道路

(a_{i}-a_{j})^{2}=a_{i}^{2}+ a_{j}^{2}-2a_{i}a_{j}

每个城市ai的度为n-1  则a_{i}^{2}}会计算n-1次

a_{i}a_{j} 可利用前缀和求

两部分相加即可

关于取模 :务必饱和时取模!吝啬你就wa了😂(一顿乱%)

#include<bits/stdc++.h>
#define ll long long 
#define mod 1000000007
using namespace std;
int n;
ll a[500005];
int main()
{
	scanf("%d",&n);
	ll ans=0;
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&a[i]) ;
		ans+=a[i]*a[i]%mod;
		ans%=mod;
	}
	ll sum=0;
	for(int i=1;i<n;i++)
	{
		sum+=a[i]*a[i-1]%mod;
		a[i]+=a[i-1];
		a[i]%=mod;		
	}
	ans*=(n-1);
	ans%=mod;
	sum*=-2;
	sum%=mod;
	ans+=sum;
	ans%=mod;
	ans+=mod;
	ans%=mod;
	printf("%lld\n",ans) ;
		
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值