A
解法:DP+二分
dp[i]=max(dp[i],dp[j]+p[i].v)(i>j)
dp[i]表示建立i点之后能够获得的最大值
int n,M; struct node { int l,v; }p[1010]; int dp[1010]; bool cmp(node a,node b){ return a.l < b.l; } bool judge_oo(){ int Max = -1; for(int i = 1;i <= n;i++) Max = max(Max,p[i].v); if(Max >= M) return 1; return 0; } bool judge_no(){ int sum = 0; for(int i = 1;i <= n;i++) sum += p[i].v; if(sum >= M) return 0; return 1; } bool judge_DP(int L){ memset(dp,0,sizeof dp); for(int i = 1;i <= n;i++){ for(int j = 0;j < i; j++){ if(p[i].l - p[j].l >= L){ dp[i] = max(dp[i],dp[j] + p[i].v); } } } int ML = 0; for(int i = 1;i <= n;i++) ML = max(ML,dp[i]); if(ML >= M) return 1; return 0; } int solve(int L,int R){ while(L + 1 < R){ int mid = (L + R)/2; if(judge_DP(mid)) L = mid; else R = mid; } return L; } int main(int argc, char *argv[]) { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int T; cin >> T; while(T--){ cin >> n >> M; for(int i = 1;i <= n;i ++) cin >> p[i].l >> p[i].v; if(judge_no()){ puts("-1"); continue; } if(judge_oo()){ puts("oo"); continue; } sort(p+1,p+n+1,cmp); p[0].l = -100000000 , p[0].v = 0; int L = 1 , R = p[n].l; cout << solve(L,R) << endl; } return 0; }
B
解法:模拟。字符串模拟
#include<stdio.h> //#include<bits/stdc++.h> #include<string.h> #include<iostream> #include<math.h> #include<sstream> #include<set> #include<queue> #include<map> #include<vector> #include<algorithm> #include<limits.h> #define inf 0x3fffffff #define INF 0x3f3f3f3f #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define LL long long #define ULL unsigned long long using namespace std; int i,j; int n,m; int num_1,num_2; int t; int sum,ans,flag; string s_1,s_2,s_3; string sss; string ss[10000]; string c; map<string,int>q1; map<string,int>q2; int main() { cin>>t; while(t--) { cin>>n>>c; num_1=0; for(i=0; i<n; i++) { cin>>sss; ans=sss.find("."); s_1=sss.substr(0,ans); s_2=sss.substr(ans+1,sss.length()); if(s_2==c) { int ans_2=sss.find("("); int ans_3=sss.find(")"); if((ans_2!=-1&&ans_2<ans_3)) { // num_1++; ss[num_1++]=sss.substr(0,ans_2); // cout<<sss.substr(0,ans_2)<<endl; } else if(ans_2==-1||ans_3==-1) { // num_1++; ss[num_1++]=sss.substr(0,ans); // cout<<sss.substr(0,ans)<<endl; } } } for(i=0; i<num_1; i++) { // cout<<ss[i]<<"A"<<endl; } // cout<<num_1<<endl; for(i=0; i<num_1; i++) { q1[ss[i]]++; } for(i=0; i<num_1; i++) { if(q2[ss[i]]==0) { q2[ss[i]]=1; if(q1[ss[i]]==1) { cout<<ss[i]<<"."<<c<<endl; } else { cout<<ss[i]<<"."<<c<<" "<<q1[ss[i]]<<endl; } } } q1.clear(); q2.clear(); } return 0; }
C
解法:树状数组寻找逆序对+预处理
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; const int M = 200010; long long ans[M + 10]; int G[M + 10],c[M + 10]; int Lowbit(int x) { return x & (-x); } void Insert(int x,int d) { while(x<=M){ c[x]+=d; x+=Lowbit(x); } } int Sum(int x) { int sum=0; while(x>0){ sum+=c[x]; x-=Lowbit(x); } return sum; } void init() { memset(G,-1,sizeof G); memset(ans,0,sizeof ans); memset(c,0,sizeof c); G[1] = 1; for(int i = 2; i <= 200100;i++){ if(G[i] == -1){ for(int j = i;j <= 200100;j += i){ if(G[j] == -1){ G[j] = i; } } } } for(int i=1;i<=200005;i++) { Insert(G[i],1); ans[i] = ans[i-1] + (i-Sum(G[i])); } } int main() { init(); int t; cin>>t; while(t--) { int n; cin>>n; cout<<ans[n]<<endl; } return 0; }
D
解法:模版题,最小覆盖圆
#include<iostream> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; const double eps=1e-8; struct Point{ double x,y; }p[505]; double dis(const Point &a,const Point &b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Point circumcenter(const Point &a,const Point &b,const Point &c) { //返回三角形的外心 Point ret; double a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2; double a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2; double d=a1*b2-a2*b1; ret.x=a.x+(c1*b2-c2*b1)/d; ret.y=a.y+(a1*c2-a2*c1)/d; return ret; } void min_cover_circle(Point *p,int n,Point &c,double &r){ //c为圆心,r为半径 random_shuffle(p,p+n); // c=p[0]; r=0; for(int i=1;i<n;i++) { if(dis(p[i],c)>r+eps) //第一个点 { c=p[i]; r=0; for(int j=0;j<i;j++) if(dis(p[j],c)>r+eps) //第二个点 { c.x=(p[i].x+p[j].x)/2; c.y=(p[i].y+p[j].y)/2; r=dis(p[j],c); for(int k=0;k<j;k++) if(dis(p[k],c)>r+eps) //第三个点 {//求外接圆圆心,三点必不共线 c=circumcenter(p[i],p[j],p[k]); r=dis(p[i],c); } } } } } int main(){ int n; Point c; double r; int t; cin>>t; while(t--) { cin>>n; for(int i=0; i<n; i++) scanf("%lf%lf",&p[i].x,&p[i].y); min_cover_circle(p,n,c,r); printf("%.1f %.1f ",c.x,c.y); } return 0; }