yp寒假训练一
19年东北四省省赛
做了J G C
补了E H
J签到题
G
题意:
给n个正方形的两个斜对角点坐标,问最小的移动可以重叠(移动上下左右一格)
思路:
一开始想的是中心pos移动,但是可能有小数,而且半径长度不知,可能有包含关系。
然后发现题目没说一定要某一个正方形移动的最小步数,那之间转换为点在面里面的移动最小,取中间的两个上下斜对角坐标就行了
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<set> 6 #include<map> 7 #include<queue> 8 #include<vector> 9 #include<queue> 10 #include<cmath> 11 #define mem(a,b) memset(a,b,sizeof(a)) 12 using namespace std; 13 #define ll long long 14 #define inf 0x3f3f3f3f 15 #define mod 998244353 16 const int maxn=1e5+10; 17 struct node{ 18 int x,y,xx,yy; 19 }a[maxn]; 20 int t,n; 21 int x[maxn<<1],y[maxn<<1]; 22 int main() 23 { 24 scanf("%d",&t); 25 while(t--){ 26 scanf("%d",&n); 27 int xt=0,yt=0; 28 for(int i=0;i<n;i++){ 29 scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].xx,&a[i].yy); 30 x[xt++]=a[i].x,x[xt++]=a[i].xx; 31 y[yt++]=a[i].y,y[yt++]=a[i].yy; 32 } 33 sort(x,x+xt); 34 sort(y,y+yt); 35 int zx=x[xt/2],zy=y[yt/2]; 36 ll sum=0; 37 for(int i=0;i<n;i++){ 38 if(zx<a[i].x || zx>a[i].xx){ 39 sum+=(ll)min(abs(a[i].x-zx),abs(a[i].xx-zx)); 40 } 41 if(zy<a[i].y || zy>a[i].yy){ 42 sum+=(ll)min(abs(a[i].y-zy),abs(a[i].yy-zy)); 43 } 44 } 45 printf("%lld\n",sum); 46 } 47 return 0; 48 }
C
题意:
给n条直线,问有多少两两相交的线,重叠也算相交的线
思路:
总量n*(n-1)/2-平行的数量
一开始算斜率,但因为斜率的精确度,wa,然后想了用gcd或者用逆元
最后用了map存y/x的最小分数yy和xx,在特判一下重叠的
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<set> 6 #include<map> 7 #include<queue> 8 #include<vector> 9 #include<queue> 10 #include<cmath> 11 #define mem(a,b) memset(a,b,sizeof(a)) 12 using namespace std; 13 #define ll long long 14 #define inf 0x3f3f3f3f 15 #define mod 998244353 16 const int maxn=1e5+10; 17 int n,t; 18 ll a,b,c,d; 19 ll gcd(ll a,ll b){ 20 return b==0?a:gcd(b,a%b); 21 } 22 struct node{ 23 ll x,y; 24 node(){} 25 node(ll xx,ll yy):x(xx),y(yy){} 26 bool operator<(const node &b)const 27 { 28 if(x==b.x) 29 return y<b.y; 30 else 31 return x<b.x; 32 } 33 }; 34 struct node1{ 35 ll x,y,chong; 36 node1(){} 37 node1(ll xx,ll yy,ll cc):x(xx),y(yy),chong(cc){} 38 bool operator<(const node1 &b)const 39 { 40 if(x==b.x){ 41 if(y==b.y){ 42 return chong<b.chong; 43 } 44 return y<b.y; 45 } 46 else 47 return x<b.x; 48 } 49 }; 50 map<node,ll>mp; 51 map<node1,ll>cd; 52 int main() 53 { 54 scanf("%d",&t); 55 while(t--){ 56 scanf("%d",&n); 57 ll zong=(ll)n*(n-1)/2; 58 for(int i=0;i<n;i++){ 59 scanf("%lld%lld%lld%lld",&a,&b,&c,&d); 60 ll xx=a-c,yy=b-d; 61 ll gd=gcd(xx,yy); 62 ll x=xx/gd,y=yy/gd; 63 ll f=x*b+y*a; 64 mp[node(x,y)]++; 65 zong-=mp[node(x,y)]; 66 cd[node1(x,y,f)]++; 67 zong+=cd[node1(x,y,f)]; 68 } 69 printf("%lld\n",zong); 70 mp.clear(),cd.clear(); 71 } 72 return 0; 73 }
E
题意:
给n个点,n-1条边,每条边都有权重,每个边形成一个最小生成树,形成线图
思路:
算每个点的贡献值,这个点的出度小于二,无贡献,大于二,就是相邻的边加一起,在最小的那个边*(相邻边数-2)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<queue> 6 #include<stack> 7 #include<algorithm> 8 #include<stdio.h> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int maxn=100010; 14 struct node 15 { 16 int v,w; 17 node(){} 18 node(int n,int m):v(n),w(m){} 19 bool operator < (const node &r)const{ 20 return w<r.w; 21 } 22 }; 23 vector<node>G[maxn]; 24 int main() 25 { 26 int T; 27 scanf("%d",&T); 28 while(T--){ 29 int n; 30 scanf("%d",&n); 31 for(int i=1;i<=n;i++)G[i].clear(); 32 for(int i=1;i<=n-1;i++){ 33 int u,v,w; 34 scanf("%d%d%d",&u,&v,&w); 35 G[u].push_back(node(v,w)); 36 G[v].push_back(node(u,w)); 37 } 38 ll ans=0; 39 for(int i=1;i<=n;i++){ 40 sort(G[i].begin(),G[i].end()); 41 int minn=0x3f3f3f3f; 42 int degree=G[i].size(); 43 for(int j=0;j<degree;j++){ 44 ans+=G[i][j].w; 45 minn=min(minn,G[i][j].w); 46 } 47 ans+=(ll)minn*(degree-2); 48 } 49 printf("%lld\n",ans); 50 } 51 return 0; 52 }
H: