第19周解题报告2篇(7月5日-7月11日)
K - City
Gym - 103145K
题意:
n城市之间连接无方向的道路,每个道路都有能量,敌人发动攻击,来摧毁这些道路,如果敌人发动x的攻击,则所有能力小于等于x的道路都将被摧毁,问有有多少对城市可以到达对方
思路:
将所有的城市道路按照能量进行从小到大的排序,根据能量的大小,将它们进行合并,每次合并操作之后计算小于等于当前这个点有多少对城市,并存入res数组,根据每次的查询,判断是否大于最大的道路的能力,如果大于,则所有道路都摧毁,没有城市可以到达对方,否则根据lower_bound计算要查询的是res数组中的第几个值
要注意的是,要进行lower_bound,则需要先将数组进行排序,排序的时候要注意是n还是m。多组样例,每次需要初始化res=0
代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<string.h>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#define int long long
typedef long long ll;
using namespace std;
typedef pair<int,int> PII;
const int N=2e5+5;
pair<PII,int>a[N];
PII p;
int f[N];
int cnt[N];
int ans=0;
int W[N];
int n,m,Q;
int res[N];//存放有多少对城市
bool cmp(pair<PII,int> xx,pair<PII,int> yy){
return xx.second<yy.second;
}
int find(int x){
if (f[x] != x)
f[x] = find(f[x]);
return f[x];
}
void merge(int a,int b){
int aa=find(a);
int bb=find(b);
if(aa!=bb){
f[aa]=bb;
// cout << "********"<<aa << " " << bb << endl;
// cout << cnt[aa] << " " << cnt[bb] << endl;
ans=ans+cnt[aa]*cnt[bb];
// cout <<"*" << ans <<endl;
cnt[bb]=cnt[bb]+cnt[aa];
cnt[aa]=0;
}
}
void init(){
ans=0;//记得初始化res
for(int i=1;i<=n;i++){
f[i]=i;//用于存父节点
cnt[i]=1;//用于计算有多少对城市
}
}
signed main()
{
//防止超时
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
cin >> n >> m >> Q;
init();//多组样例初始化
for(int i=1;i<=m;i++){
int x,y,w;
cin >> x >> y >> w;
p.first=x;
p.second=y;
a[i].first=p;//城市道路两端点
a[i].second=w;//道路的能量
W[i]=w; //城市道路的能量存入W
}
sort(a+1,a+1+m,cmp);
for(int i=m;i>=1;i--){
merge(a[i].first.first,a[i].first.second);
res[i]=ans;
}
sort(W+1,W+1+m);//注意要排序
// for(int i=1;i<=m;i++){
// cout << res[i];
// }
while(Q--){
int x;
cin >> x;
// for(int i=1;i<=m;i++){
// if(W[i]>=x){
// temp=i;
// break;
// }
// }
// cout << temp << "*" << endl;
if(x>a[m].second){//所有城市道路都摧毁
cout << 0 << endl;
}
else{
int temp=lower_bound(W+1,W+1+m,x)-W;
cout << res[temp] << endl;
}
}
}
return 0;
}
/**
5
2 1 2
1 2 4
3
**/
J - Transform
题意:
在三维空间内给出两个点(a,b,c)和(x,y,z),前一个点与原点所连成的直线为l,将第二个点绕直线l旋转r度和-r度,输出旋转后纵坐标高的那个点的坐标
思路:
假设旋转轴的单位向量为(vx,vy,vz),旋转前的坐标为(oldx,oldy,oldz),旋转后的坐标为(nx,ny,nz),旋转角度为theta,则有公式
node get(double oldx, double oldy, double oldz, double vx, double vy, double vz, double theta){
double r = theta * PI / 180;
double c = cos(r);
double s = sin(r);
double nx = (vx*vx*(1 - c) + c) * oldx + (vx*vy*(1 - c) - vz*s) * oldy + (vx*vz*(1 - c) + vy*s) * oldz;
double ny = (vy*vx*(1 - c) + vz*s) * oldx + (vy*vy*(1 - c) + c) * oldy + (vy*vz*(1 - c) - vx*s) * oldz;
double nz = (vx*vz*(1 - c) - vy*s) * oldx + (vy*vz*(1 - c) + vx*s) * oldy + (vz*vz*(1 - c) + c) * oldz;
return node(nx, ny, nz);
}
如果setprecision(n)与setiosflags(ios::fixed)合用,可以控制小数点右边的数字个数。格式为
if(p1.z>p2.z) cout<<fixed<<setprecision(9)<<p1.x<<" "<<p1.y<<" "<<p1.z<<endl;
else cout<<fixed<<setprecision(9)<<p2.x<<" "<<p2.y<<" "<<p2.z<<endl
代码:
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<string.h>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#define PI acos(-1)
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef pair<int,int> PII;
struct node{
node(double _x, double _y, double _z){
x = _x;
y = _y;
z = _z;
}
double x;
double y;
double z;
};
node get(double oldx, double oldy, double oldz, double vx, double vy, double vz, double theta){
double r = theta * PI / 180;
double c = cos(r);
double s = sin(r);
double nx = (vx*vx*(1 - c) + c) * oldx + (vx*vy*(1 - c) - vz*s) * oldy + (vx*vz*(1 - c) + vy*s) * oldz;
double ny = (vy*vx*(1 - c) + vz*s) * oldx + (vy*vy*(1 - c) + c) * oldy + (vy*vz*(1 - c) - vx*s) * oldz;
double nz = (vx*vz*(1 - c) - vy*s) * oldx + (vy*vz*(1 - c) + vx*s) * oldy + (vz*vz*(1 - c) + c) * oldz;
return node(nx, ny, nz);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--){
double a,b,c,x,y,z,r;
cin>>a>>b>>c>>x>>y>>z>>r;
double len=sqrtf(a*a+b*b+c*c);
node p1=get(x,y,z,a/len,b/len,c/len,r);
node p2=get(x,y,z,a/len,b/len,c/len,-r);
if(p1.z>p2.z){
printf("%.9lf %.9lf %.9lf\n",p1.x,p1.y,p1.z);
// cout << p1.x << " " << p1.y << " " << p1.z << endl;
}
else{
printf("%.9lf %.9lf %.9lf\n",p2.x,p2.y,p2.z);
// cout << p2.x << " " << p2.y << " " << p2.z << endl;
}
}
return 0;
}