• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Codeforces Edu 87 題解

    標簽: 題解

    Codeforces Edu 87

    C. Simple Polygon Embedding【三分+計算幾何】

    題目

    對于一個邊長為1的正2n2n邊形,求其最小覆蓋正方形的邊長

    題解

    如果nn為偶數,那么該正多邊形可以旋轉成如下形式

    在這里插入圖片描述

    其中四條邊與正方形邊界平行,因此正方形的邊長計算公式為
    ans=1tanπ2n ans=\frac{1}{tan\frac{\pi}{2n}}
    而如果nn為奇數,不論怎么旋轉最多只有兩條邊與正方形邊界平行

    在這里插入圖片描述

    因此,可以用三分的方法在旋轉過程中找到一個最小覆蓋正方形。根據對稱性,旋轉角度只需要在0π2n0\sim \frac{\pi}{2n}。實際上,由對稱性不難猜出,應該在旋轉的中間位置,即π4n\frac{\pi}{4n}取到最小值,因此公式為
    ans=cos?(π4n)sin?(π2n) ans=\frac{\cos(\frac{\pi}{4n})}{\sin(\frac{\pi}{2n})}
    這里給出nn為奇數時用三分的方法尋找最小值的過程

    在這里插入圖片描述

    用兩個向量X,Y追蹤旋轉過程中最小覆蓋正方形邊長的變化,正方形的邊長就等于max(Xx,Yy)?2max(X向量在x軸方向投影,Y向量在y軸方向投影)*2

    題解

    #include <bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    #define endl '\n'
    #define pi acos(-1)
    typedef long long ll;
    const int INF = 1 << 30;
    const double eps = 1e-8;
    struct Point {	// 點類
    	double x, y;
    	Point() {};
    	Point(double x, double y): x(x), y(y) {}
    	void operator=(const Point&a) {
    		x = a.x, y = a.y;
    	}
    };
    typedef Point Vector;
    double Dot(Vector A, Vector B) {return A.x * B.x + A.y * B.y;}
    double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}
    double Len(Vector A) {return sqrt(Dot(A, A));}	// 向量長度
    Vector Rotate(Vector A, double rad)
    // 向量逆時針旋轉
    {
    	return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
    }
    
    int n;
    Vector X, Y; // 分別監測旋轉過程中x,y的最小最大值
    
    double cal(double rad)
    // 計算旋轉后最小正方形邊長
    {
    	Vector tempx = Rotate(X, rad);
    	Vector tempy = Rotate(Y, rad);
    	return max(tempx.x, tempy.y) * 2;
    }
    double tsearch(double left, double right)
    {
    	double ans = INF;
    	double mid, midmid;
    	while (right - left > eps) {
    		mid = (left + right) / 2;
    		midmid = (mid + right) / 2;
    		double ans1 = cal(mid), ans2 = cal(midmid);
    		if (ans1 < ans2) {
    			right = midmid;
    			ans = min(ans, ans1);
    		}
    		else {
    			left = mid;
    			ans = min(ans, ans2);
    		}
    	}
    	return ans;
    }
    int main()
    {
    	ios::sync_with_stdio(0), cin.tie(0);
    	int t; cin >> t;
    	while (t--) {
    		cin >> n;
    		X.x = 0.5 / sin(pi / (2 * n)), X.y = 0;
    		Y.x = 0.5, Y.y = 0.5 / tan(pi / (2 * n));
    		double sta = 0, end = pi / (2 * n);	// 旋轉范圍
    		cout << fixed << setprecision(8) << tsearch(sta, end) << endl;
    	}
    	return 0;
    }
    

    D. Multiset【二分答案】

    題目

    給定一個具有nn個元素的集合,有qq次操作,每次操作給定一個整數kk,規則如下:

    1. 如果k1k\ge 1,則把kk加入集合中;
    2. 如果k<0k<0,則從集合中按升序排序后,移除第k|k|個元素

    如果最終集合非空,輸出任一集合中元素即可

    • Memory limit: 28mb

    題解

    本題可以選擇用線段樹之類的數據結構來模擬題目中的操作,但需要進行一定的優化,因為本題空間限制非常嚴格。

    實際上,考慮到最終只需要輸出集合中的任意一個元素即可,不妨假設要輸出最小的一個,那么可以用二分答案的方法來查找。

    二分查找的思路為:
    定義函數count(x)表示:對于元素x,最終集合中小于等于x的元素個數。
    最終答案就應該是找到一個最小的x滿足count(x)>0count(x)>0

    因為在本題中,集合中元素不唯一,并且不一定是連續的。
    假設最終集合中最小的元素是y,那么在二分過程中,任何大于等于y的數返回結果都是1\ge 1,而比y小的數返回結果都是0,因此y就是那個滿足count(x)>0的最小元素

    對于最終集合為空的情況,可以用一個非常大的數去檢驗。因為集合中元素a[i]106a[i]\le 10^6,如果最終集合中小于等于10910^9的元素為0,就說明集合中不可能存在任何元素。(如果count(1e9)==0count(1e9)==0,就說明最終集合中的最小元素必定是大于1e91e9的,而這與集合中元素1e6\le 1e6相矛盾)

    if (count(int(1e9)) == 0) {
        cout << 0 << endl;
    }
    

    代碼

    #include <bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    #define endl '\n'
    typedef long long ll;
    const int maxn = 1e6 + 10;
    int n, q;
    vector<int>a, k;
    int count(int x)
    // 計算最終集合里面小于等于x的元素個數
    {
    	int cnt = 0;
    	for (int i = 0; i < n; i++) {	// 初始化
    		if (a[i] <= x) cnt++;
    	}
    	for (int i = 0; i < q; i++) {
    		if (k[i] > 0 && k[i] <= x) cnt++;	// 插入正數,并且比x小,必然會排在x前面
    		if (k[i] < 0 && abs(k[i]) <= cnt) cnt--;	// 插入負數,如果其絕對值<=cnt,就會刪除x左側的元素
    	}
    	return cnt;
    }
    int main()
    {
    	ios::sync_with_stdio(0), cin.tie(0);
    	cin >> n >> q;
    	a.resize(n); k.resize(q);
    	for (int i = 0; i < n; i++) {
    		cin >> a[i];
    	}
    	for (int i = 0; i < q; i++) {
    		cin >> k[i];
    	}
    	if (count(int(1e9)) == 0) {	// 判斷最終集合是否為空
    		cout << 0 << endl;
    		return 0;
    	}
    	int left = 1, right = int(1e6) + 1;
    	while (left < right) {
    		int mid = left + (right - left) / 2;
    		if (count(mid) <= 0) left = mid + 1;
    		else right = mid;
    	}
    	cout << right << endl;
        return 0;
    }
    
    版權聲明:本文為qq_43346369原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/qq_43346369/article/details/106233731

    智能推薦

    Codeforces Round #432 題解

    比賽鏈接:http://codeforces.com/contest/851 A. Arpa and a research in Mexican wave 題意:balabala 解法:找個規律。。 B. Arpa and an exam about geometry 題意:給你3個點的坐標,問你是否能找到一個點,以該點為中心旋轉一定的角度使得a與b重合,b與c重合 解法:直接判斷只要兩個線段長度...

    Codeforces Round #621題解

    A、 Cow and HaybalesCow\ and\ HaybalesCow and Haybales 貪心模擬題。 B、 Cow and FriendCow\ and\ FriendCow and Friend 問最少幾步,根據三角形定理知道若以a為步長,跳兩步可組成(0,2a]之間任意值。 1.a<=x時...

    Codeforces Round #564 題解

    A. Nauuo and Cards time limit per test 1.5 seconds memory limit per test 256 megabytes input standard input output standard output Nauuo is a girl who loves playing cards. One day she was playing card...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    猜你喜歡

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    精品国产乱码久久久久久蜜桃不卡