ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 虚构推理

2021-10-03 07:00:07  阅读:158  来源: 互联网

标签:node 虚构 题解 ans t2 t1 int double 推理


传送门

首先有一个三分的思路:
考虑每个指针与某个给定指针的偏角,在一分钟内为单谷函数
给它们取max还是单谷函数,于是可以是三分
check的时候貌似可以set优化,%zjx,我就先咕了

正解的话考虑二分
发现对于一个给定的偏角范围,每个指针都有一个合法区间
于是对区间求交集,用珂朵莉树实现
最后特殊处理一下时针范围对分针范围的限制即可

Code:
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48), c=getchar();
	return ans*f;
}

int n, lst;
int p[N];
const double step1=360.0/43200.0;
const double step2=360.0/3600.0;
const double eps=1e-10;

namespace force{
	inline double calch(int a, int b) {
		a%=43200, b%=43200;
		double t1=step1*a, t2=step1*b, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calcm(int a, int b) {
		a%=3600, b%=3600;
		double t1=a*step2, t2=b*step2, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	void solve() {
		double ans=360;
		for (int i=1,a,b,c; i<=n; ++i) {
			a=read(); b=read(); c=read();
			p[i]=a*3600+b*60+c;
		}
		for (int i=0; i<43200; ++i) {
			double dlth=0, dltm=0;
			for (int j=1; j<=n; ++j) {
				dlth=max(dlth, calch(i, p[j]));
				dltm=max(dltm, calcm(i, p[j]));
			}
			// cout<<"dlt: "<<dlth<<' '<<dltm<<endl;
			ans=min(ans, max(dlth, dltm));
		}
		printf("%.7lf\n", ans);
		exit(0);
	}
}

namespace task1{
	inline double calch(double a, int b) {
		b%=43200;
		double t1=step1*a, t2=step1*b, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calcm(double a, int b) {
		b%=3600;
		double t1=a*step2, t2=b*step2, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calc(int h, double t) {
		double ans=0;
		for (int i=1; i<=n; ++i) {
			ans=max(ans, calch(t+h*60, p[i]));
			ans=max(ans, calcm(t+(h%60)*60, p[i]));
		}
		return ans;
	}
	void solve() {
		double ans=360;
		for (int i=0; i<720; ++i) {
			double lside=0, rside=60, lmid, rmid, tem;
			for (int j=1; j<=50; ++j) {
				// cout<<"ij: "<<i<<' '<<j<<' '<<lside<<' '<<rside<<' '<<calc(i, lmid)<<' '<<calc(i, rmid)<<endl;
				lmid=lside+(rside-lside)/3.0, rmid=lside+2.0*(rside-lside)/3.0;
				if ((tem=calc(i, lmid))<calc(i, rmid)) rside=rmid;
				else lside=lmid;
				// if (j>5 && tem>ans+5) break;
			}
			ans=min(ans, calc(i, lside));
		}
		printf("%.10lf\n", ans);
		exit(0);
	}
}

namespace task2{
	int sta[N];
	inline double calch(double a, int b) {
		b%=43200;
		double t1=step1*a, t2=step1*b, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calcm(double a, int b) {
		b%=3600;
		double t1=a*step2, t2=b*step2, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calc(int h, double t) {
		double ans=0;
		for (int i=1; i<=n; ++i) {
			ans=max(ans, calch(t+h*60, p[i]));
			ans=max(ans, calcm(t+(h%60)*60, p[i]));
		}
		return ans;
	}
	void solve() {
		random_device(seed);
		srand(seed());
		double ans=360;
		for (int i=0; i<720; ++i) sta[i]=i;
		random_shuffle(sta+1, sta+n+1);
		for (int i=0; i<720; ++i) {
			// cout<<"i: "<<i<<endl;
			if (clock()>1900000) break;
			double lside=0, rside=60, lmid, rmid, tem;
			for (int j=1; j<=50; ++j) {
				// cout<<"ij: "<<i<<' '<<j<<' '<<lside<<' '<<rside<<' '<<calc(i, lmid)<<' '<<calc(i, rmid)<<endl;
				lmid=lside+(rside-lside)/3.0, rmid=lside+2.0*(rside-lside)/3.0;
				if ((tem=calc(sta[i], lmid))<calc(sta[i], rmid)) rside=rmid;
				else lside=lmid;
				if (j>5 && tem>ans+2) break;
				if (j>10 && tem>ans+0.1) break;
				if (j>20 && tem>ans+0.005) break;
			}
			ans=min(ans, calc(sta[i], lside));
		}
		printf("%.10lf\n", ans);
		exit(0);
	}
}

namespace task3{
	int p[N];
	inline double calch(double a, int b) {
		b%=43200;
		double t1=step1*a, t2=step1*b, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calcm(double a, int b) {
		b%=3600;
		double t1=a*step2, t2=b*step2, ans=max(t1, t2)-min(t1, t2);
		if (ans>180.0) ans=360.0-ans;
		return ans;
	}
	inline double calc(int h, double t) {
		double ans=0;
		for (int i=1; i<=n; ++i) {
			ans=max(ans, calch(t+h*60, p[i]));
			ans=max(ans, calcm(t+(h%60)*60, p[i]));
		}
		return ans;
	}
	void solve() {
		double ans=360;
		for (int i=lst*60; i<=lst*60+30; ++i) {
			// cout<<"i: "<<i<<endl;
			if (clock()>1700000) break;
			double lside=0, rside=60, lmid, rmid, tem;
			for (int j=1; j<=50; ++j) {
				// cout<<"ij: "<<i<<' '<<j<<' '<<lside<<' '<<rside<<' '<<calc(i, lmid)<<' '<<calc(i, rmid)<<endl;
				lmid=lside+(rside-lside)/3.0, rmid=lside+2.0*(rside-lside)/3.0;
				if ((tem=calc(i, lmid))<calc(i, rmid)) rside=rmid;
				else lside=lmid;
				// if (j>5 && tem>ans+5) break;
				// if (j>10 && tem>ans+1) break;
				// if (j>20 && tem>ans+0.5) break;
			}
			ans=min(ans, calc(i, lside));
		}
		printf("%.10lf\n", ans);
		exit(0);
	}
}

namespace task{
	int top, rtop;
	double sta[N];
	struct odt{
		struct node{
			double l, r;
			node(double a, double b):l(a),r(b){}
			friend inline bool operator < (node a, node b) {return a.l<b.l;}
		};
		set<node> s;
		odt(){s.insert(node(0.0, 360.0-eps));}
		inline void clear() {s.clear(); s.insert(node(0.0, 360.0-eps));}
		set<node>::iterator split(double pos) {
			auto it=s.lower_bound(node(pos, 0));
			if (it!=s.end() && it->l==pos) return it;
			--it; node tem=*it; s.erase(it);
			s.insert(node(tem.l, pos-eps));
			return s.insert(node(pos, tem.r)).first;
		}
		void ins1(double l, double r) {
			// cout<<"ins1: "<<l<<' '<<r<<endl;
			auto it=s.lower_bound(node(l, 0));
			if (it!=s.begin()) {
				--it;
				// printf("it: %.6lf %.6lf\n", it->l, it->r);
				if (it->r>=l) it=split(l);
				else ++it;
			}
			if (it!=s.begin()) s.erase(s.begin(), it);
			it=s.lower_bound(node(r+eps, 0));
			if (it!=s.begin()) {
				--it;
				if (it->r>r) it=split(r+eps);
				else ++it;
			}
			if (it!=s.end()) s.erase(it, s.end());
		}
		void ins2(double l, double r) {
			// cout<<"ins2: "<<l<<' '<<r<<endl;
			auto it1=s.lower_bound(node(l+eps, 0));
			if (it1!=s.begin()) {
				--it1;
				if (it1->r>=l) it1=split(l+eps);
				else ++it1;
			}
			auto it2=s.lower_bound(node(r, 0));
			if (it2!=s.begin()) {
				--it2;
				if (it2->r>r) it2=split(r);
				else ++it2;
			}
			it1=s.lower_bound(node(l+eps, 0));
			if (it1!=it2) s.erase(it1, it2);
		}
		double maxlenth() {
			double ans=0;
			for (auto it:s) ans=max(ans, it.r-it.l);
			return ans;
		}
		void del(double l, double r) {
			// cout<<"del: "<<l<<' '<<r<<endl;
			auto it=s.lower_bound(node(l, 0));
			if (it!=s.begin()) {
				--it;
				if (it->r>l) it=split(l);
				else ++it;
			}
			// printf("it: %.6lf %.6lf\n", it->l, it->r);
			it=s.lower_bound(node(r, 0));
			if (it!=s.begin()) {
				--it;
				if (it->r>=r) it=split(r);
				else ++it;
			}
			auto it1=s.lower_bound(node(l, 0)), it2=it;
			if (it1!=it2) s.erase(it1, it2);
		}
	}tr1, tr2, tr;
	struct range{
		double l, r;
		inline void build(double a, double b) {l=a; r=b;}
		friend inline bool operator < (range a, range b) {return a.l<b.l;}
	}rg[N];
	bool check(double dlt) {
		// cout<<"check: "<<dlt<<endl;
		tr1.clear(); tr2.clear();
		for (int j=1; j<=n; ++j) {
			// cout<<"j: "<<j<<endl;
			int k;
			double now;

			k=p[j]%43200;
			now=k*step1;
			// cout<<"now: "<<now<<endl;
			if (now-dlt<0) tr1.ins2(now+dlt, 360.0+(now-dlt));
			else if (now+dlt>=360.0) tr1.ins2(now+dlt-360.0, now-dlt);
			else tr1.ins1(now-dlt, now+dlt);

			k=p[j]%3600;
			now=k*step2;
			// cout<<"now: "<<now<<endl;
			if (now-dlt<0) tr2.ins2(now+dlt, 360.0+(now-dlt));
			else if (now+dlt>=360.0) tr2.ins2(now+dlt-360.0, now-dlt);
			else tr2.ins1(now-dlt, now+dlt);
			// cout<<"s1: "; for (auto it:tr1.s) cout<<it.l<<','<<it.r<<' '; cout<<endl;
			// cout<<"s2: "; for (auto it:tr2.s) cout<<it.l<<','<<it.r<<' '; cout<<endl;
		}
		// cout<<"return "<<(tr1.s.size()&&tr2.s.size())<<endl;
		if (!(tr1.s.size()&&tr2.s.size())) return 0;
		if (tr1.maxlenth()>=30.0) return 1;
		// cout<<"tr1: "; for (auto it:tr1.s) cout<<fixed<<setprecision(10)<<it.l<<','<<it.r<<' '; cout<<endl;
		// cout<<"tr2: "; for (auto it:tr2.s) cout<<fixed<<setprecision(10)<<it.l<<','<<it.r<<' '; cout<<endl;
		rtop=0;
		for (auto it:tr1.s) {
			double l=it.l, r=it.r;
			int a=floor(l/30), b=floor(r/30);
			if (a==b) rg[++rtop].build((l-30.0*a)*12.0, (r-30.0*b)*12.0);
			else {
				rg[++rtop].build(0, (r-30.0*b)*12.0);
				rg[++rtop].build((l-30.0*a)*12.0, 360.0);
			}
		}
		sort(rg+1, rg+rtop+1);
		range lst;
		top=0; sta[++top]=0.0-eps;
		for (int i=1; i<=rtop; ++i) {
			if (i==1) lst=rg[i];
			else if (lst.r<rg[i].l) {sta[++top]=lst.l; sta[++top]=lst.r; lst=rg[i];}
			else lst.r=max(lst.r, rg[i].r);
		}
		if (rtop) sta[++top]=lst.l, sta[++top]=lst.r;
		sta[++top]=360.0;
		sort(sta+1, sta+top+1);
		// cout<<"top: "<<top<<' '<<rtop<<endl;
		// cout<<"rg: "; for (int i=1; i<=rtop; ++i) cout<<rg[i].l<<','<<rg[i].r<<' '; cout<<endl;
		// cout<<"sta: "; for (int i=1; i<=top; ++i) cout<<sta[i]<<' '; cout<<endl;
		for (int i=1; i<top&&rtop; i+=2) {
			if (sta[i]+eps>sta[i+1]-eps) continue;
			tr2.del(sta[i]+eps, sta[i+1]-eps);
			// cout<<"tr1: "; for (auto it:tr1.s) cout<<fixed<<setprecision(10)<<it.l<<','<<it.r<<' '; cout<<endl;
			// cout<<"tr2: "; for (auto it:tr2.s) cout<<fixed<<setprecision(10)<<it.l<<','<<it.r<<' '; cout<<endl;
		}
		return tr1.s.size()&&tr2.s.size();
	}
	void solve() {
		// tr.ins2(47.6, 350); tr.ins1(47.3, 100);
		// cout<<"s: "; for (auto it:tr.s) cout<<it.l<<','<<it.r<<' '; cout<<endl;
		// exit(0);

		// cout<<check(178.594)<<endl;
		// exit(0);
		double l=0, r=180.0-eps, mid;
		bool tem;
		for (int i=1; i<=50; ++i) {
			mid=(l+r)/2;
			// cout<<fixed<<setprecision(10)<<"mid: "<<l<<' '<<r<<' '<<mid<<endl;
			if (tem=check(mid)) r=mid;
			else l=mid;
			// cout<<"return "<<tem<<endl;
		}
		printf("%.10lf\n", l);
		exit(0);
	}
}

signed main()
{
	freopen("unreal.in", "r", stdin);
	freopen("unreal.out", "w", stdout);
	bool allsame=1;

	n=read();
	for (int i=1,a,b,c; i<=n; ++i) {
		a=read(); b=read(); c=read();
		if (i!=1 && a!=lst) allsame=0;
		p[i]=a*3600+b*60+c;
		lst=a;
	}
	// if (n<=1000) task1::solve();
	// else task2::solve();
	task::solve();

	return 0;
}

标签:node,虚构,题解,ans,t2,t1,int,double,推理
来源: https://www.cnblogs.com/narration/p/15363328.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有