日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P1955 [NOI2015]程序自动分析 离散化学习 lower_bound学习

發(fā)布時間:2025/3/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P1955 [NOI2015]程序自动分析 离散化学习 lower_bound学习 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目鏈接

https://www.luogu.org/problemnew/show/P1955

題目描述

在實現(xiàn)程序自動分析的過程中,常常需要判定一些約束條件是否能被同時滿足。

考慮一個約束滿足問題的簡化版本:假設(shè)x1,x2,x3...代表程序中出現(xiàn)的變量,給定n個形如xi=xj或xi≠xj的變量相等/不等的約束條件,請判定是否可以分別為每一個變量賦予恰當(dāng)?shù)闹?#xff0c;使得上述所有約束條件同時被滿足。例如,一個問題中的約束條件為:x1=x2,x2=x3,x3=x4,x4≠x1,這些約束條件顯然是不可能同時被滿足的,因此這個問題應(yīng)判定為不可被滿足。

現(xiàn)在給出一些約束滿足問題,請分別對它們進行判定。

輸入輸出格式

輸入格式:

從文件prog.in中讀入數(shù)據(jù)。

輸入文件的第1行包含1個正整數(shù)t,表示需要判定的問題個數(shù)。注意這些問題之間是相互獨立的。

對于每個問題,包含若干行:

第1行包含1個正整數(shù)n,表示該問題中需要被滿足的約束條件個數(shù)。接下來n行,每行包括3個整數(shù)i,j,e,描述1個相等/不等的約束條件,相鄰整數(shù)之間用單個空格隔開。若e=1,則該約束條件為xi=xj;若e=0,則該約束條件為xi≠xj;

輸出格式:

輸出到文件 prog.out 中。

輸出文件包括t行。

輸出文件的第 k行輸出一個字符串“ YES” 或者“ NO”(不包含引號,字母全部大寫),“ YES” 表示輸入中的第k個問題判定為可以被滿足,“ NO” 表示不可被滿足。

輸入輸出樣例

輸入樣例#1:? 2 2 1 2 1 1 2 0 2 1 2 1 2 1 1 輸出樣例#1:? NO YES 輸入樣例#2:? 2 3 1 2 1 2 3 1 3 1 1 4 1 2 1 2 3 1 3 4 1 1 4 0 輸出樣例#2:? YES NO

說明

【樣例解釋1】

在第一個問題中,約束條件為:x1=x2,x1≠x2。這兩個約束條件互相矛盾,因此不可被同時滿足。

在第二個問題中,約束條件為:x1=x2,x1=x2。這兩個約束條件是等價的,可以被同時滿足。

【樣例說明2】

在第一個問題中,約束條件有三個:x1=x2,x2=x3,x3=x1。只需賦值使得x1=x1=x1,即可同時滿足所有的約束條件。

在第二個問題中,約束條件有四個:x1=x2,x2=x3,x3=x4,x4≠x1。由前三個約束條件可以推出x1=x2=x3=x4,然而最后一個約束條件卻要求x1≠x4,因此不可被滿足。

【數(shù)據(jù)范圍】

【時限2s,內(nèi)存512M】

題目分析

這道題是一個很顯然的并查集,但是看到數(shù)據(jù)范圍

我們竟然需要開一個1e9的數(shù)組!

那么很顯然的會MLE

所以我們要用到離散化

然后就可以了qwq

參考代碼

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 //#define DEBUG(x) cerr << #x << "=" << x << endl 8 const int maxn = 1e5 + 7; 9 10 int n, t, f[maxn], book[maxn * 3]; 11 12 struct node 13 { 14 int x; 15 int y; 16 int e; 17 }a[maxn]; 18 19 bool cmp(node a, node b) 20 { 21 return a.e > b.e; 22 } 23 24 inline void first(int k) 25 { 26 for (int i = 1; i <= k; i++) f[i] = i; 27 } 28 29 int get(int x) 30 { 31 return f[x] == x ? x : f[x] = get(f[x]); 32 } 33 34 int main() 35 { 36 ios::sync_with_stdio(false); 37 cin.tie(0); 38 cin >> t; 39 while (t--) 40 { 41 cin >> n; 42 int tot = -1; 43 int flag = 1; 44 memset(a, 0, sizeof(a)); 45 memset(f, 0, sizeof(f)); 46 memset(book, 0, sizeof(book)); 47 for (int i = 1; i <= n; i++) 48 { 49 cin >> a[i].x >> a[i].y >> a[i].e; 50 book[++tot] = a[i].x; 51 book[++tot] = a[i].y; 52 } 53 sort(book, book + tot); 54 int reu = unique(book, book + tot) - book; 55 for (int i = 1; i <= n; i++) 56 { 57 a[i].x = lower_bound(book, book + reu, a[i].x) - book; 58 a[i].y = lower_bound(book, book + reu, a[i].y) - book; 59 } 60 first(reu); 61 sort(a + 1, a + n + 1, cmp); 62 for (int i = 1; i <= n; i++) 63 { 64 int r1 = get(a[i].x); 65 int r2 = get(a[i].y); 66 if (a[i].e) 67 { 68 f[r1] = r2; 69 } 70 else if (r1 == r2) 71 { 72 cout << "NO" << endl; 73 flag = 0; 74 break; 75 } 76 } 77 if (flag) 78 cout << "YES" << endl; 79 } 80 return 0; 81 }

離散化

定義

離散化,把無限空間中有限的個體映射到有限的空間中去,以此提高算法的時空效率。 通俗的說,離散化是在不改變數(shù)據(jù)相對大小的條件下,對數(shù)據(jù)進行相應(yīng)的縮小。例如: 原數(shù)據(jù):1, 999, 100000, 15; 處理后:1, 3, 4, 2; 原數(shù)據(jù):{100, 200},{20, 50000},{1, 400}; 處理后:{3, 4},{2, 6},{1, 5};

對于離散化來說主要有三個步驟

一.去重(用unique去重函數(shù))

二.排序

三.二分索引(用lower_bound函數(shù))

1 const int N = 1e5 + 7; 2 3 int t[N], a[N]; 4 5 int main() 6 { 7 std::ios::sync_with_stdio(false); 8 cin.tie(0); 9 cin >> n; 10 for (int i = 1; i <= n; i++) 11 { 12 cin >> a[i]; 13 t[i] = a[i]; 14 } 15 sort(t + 1, t + n + 1); 16 m = unique(t + 1, t + n + 1) - t - 1; 17 for (int i = 1; i <= n; i++) 18 a[i] = lower_bound(t + 1, t + m + 1, a[i]) - t; 19 }

在這段代碼中,a[ ]經(jīng)過離散,范圍就變成了m。解釋一下,unique是c++自帶的一個函數(shù),表示對一個數(shù)列去重,然后返回不重復(fù)的元素個數(shù),當(dāng)然在后面要減去首地址。那么這種離散化對于有重復(fù)元素的數(shù)列也可以適用,但是復(fù)雜度會高些。有一種離散化的方式復(fù)雜度會低一些,但是不能處理有重復(fù)元素的數(shù)列,所以在此不再贅述

舉個例子:原數(shù)據(jù):{6, 8, 4, 9, 5, 6, 7, 4},首先排序后得到{4, 4, 5, 6, 6, 7, 8, 9},去重{4, 5, 6, 7, 8, 9},然后原序列就變成了{3, 5, 1, 6, 2, 3, 4, 1}。

lower_bound( )

這里是關(guān)于lower_bound( )和upper_bound( )的常見用法

lower_bound( )和upper_bound( )都是利用二分查找的方法在一個排好序的數(shù)組中進行查找的,這兩個函數(shù)都需要加載頭文件#include<algorithm>

從小到大的排序數(shù)組中,

lower_bound( begin,end,num):從數(shù)組的begin位置到end-1位置二分查找第一個大于或等于num的數(shù)字,找到返回該數(shù)字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數(shù)字在數(shù)組中的下標。

upper_bound( begin,end,num):從數(shù)組的begin位置到end-1位置二分查找第一個大于num的數(shù)字,找到返回該數(shù)字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數(shù)字在數(shù)組中的下標。

從大到小的排序數(shù)組中,重載lower_bound()和upper_bound()

lower_bound( begin,end,num,greater<type>() ):從數(shù)組的begin位置到end-1位置二分查找第一個小于或等于num的數(shù)字,找到返回該數(shù)字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數(shù)字在數(shù)組中的下標。

upper_bound( begin,end,num,greater<type>() ):從數(shù)組的begin位置到end-1位置二分查找第一個小于num的數(shù)字,找到返回該數(shù)字的地址,不存在則返回end。通過返回的地址減去起始地址begin,得到找到數(shù)字在數(shù)組中的下標。

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 //#define DEBUG(x) cerr << #x << "=" << x << endl 8 #define LL long long 9 const int maxn = 1e5 + 10; 10 const int INF = 2 * int(1e9) + 10; 11 12 int cmd(int a, int b) 13 { 14 return a > b; 15 } 16 17 int main() 18 { 19 ios::sync_with_stdio(false); 20 cin.tie(0); 21 int num[6] = {1, 2, 4, 7, 15, 34}; 22 sort(num, num + 6); //按從小到大排序 23 int pos1 = lower_bound(num, num + 6, 7) - num; //返回數(shù)組中第一個大于或等于被查數(shù)的值 24 int pos2 = upper_bound(num, num + 6, 7) - num; //返回數(shù)組中第一個大于被查數(shù)的值 25 cout << pos1 << " " << num[pos1] << endl; 26 cout << pos2 << " " << num[pos2] << endl; 27 sort(num, num + 6, cmd); //按從大到小排序 28 int pos3 = lower_bound(num, num + 6, 7, greater<int>()) - num; //返回數(shù)組中第一個小于或等于被查數(shù)的值 29 int pos4 = upper_bound(num, num + 6, 7, greater<int>()) - num; //返回數(shù)組中第一個小于被查數(shù)的值 30 cout << pos3 << " " << num[pos3] << endl; 31 cout << pos4 << " " << num[pos4] << endl; 32 return 0; 33 }

?

轉(zhuǎn)載于:https://www.cnblogs.com/aiyi2000/p/9818985.html

總結(jié)

以上是生活随笔為你收集整理的P1955 [NOI2015]程序自动分析 离散化学习 lower_bound学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。