hdu4334:Trouble(two pointers, 思維)
阿新 • • 發佈:2019-02-14
getch fine algo namespace hash表 其中 直接退出。 show 網上
???似乎可行,於是便開打。
???一提交,TLE了。
???進行一波卡常,還是TLE了。
???那麽這麽做不可行嗎?可行!網上也有許多大佬用這方法A了此題。可能是本蒟蒻太弱,常數太大...
???這裏介紹用two pointers做的做法。
???首先把前兩個集合中的數兩兩相加,再將第3與4個集合中的數兩兩相加,得到兩個數組。
???將兩個數組都從小到大sort一次。
???枚舉第5個集合中的數,對於集合中的每個數,創建l,r兩個指針,分別指向兩個數組其中一個的頭與另一個的尾。
???若三個數相加>0,則將尾的指針向左移一位。
???若<0,則將頭的指針向右移一位。
???若=0則輸出Yes,直接退出。
???若不能得出0,則輸出No。
???一個比較巧妙的做法,無法理解的話可以畫個圖自行理解理解。
???時間復雜度O(n^3)。
原題鏈接
題目描述:給定5個集合,從每個集合中選一個數,使得5個數的和為0.
輸入格式:第一行:一個整數t表示數據組數。
接下來t組數據,每組數據第一行一個整數表示集合的大小。
接下來5行,每行n個數表示集合中的i元素。
輸出格式:對於每組數據,輸出Yes或No表示是否可以使數的和為0.
輸入樣例:
2
2
1 -1
1 -1
1 -1
1 -1
1 -1
3
1 2 3
-1 -2 -3
4 5 6
-1 3 2
-4 -10 -1
輸出樣例:
No
Yes
解析:一看到題目,n^5進行枚舉肯定不可取。
???那麽先n^2預處理前2個集合數的和,經行hash,後n^3枚舉後三行,在hash表中查。
???一提交,TLE了。
???進行一波卡常,還是TLE了。
???那麽這麽做不可行嗎?可行!網上也有許多大佬用這方法A了此題。可能是本蒟蒻太弱,常數太大...
???這裏介紹用two pointers做的做法。
???首先把前兩個集合中的數兩兩相加,再將第3與4個集合中的數兩兩相加,得到兩個數組。
???將兩個數組都從小到大sort一次。
???枚舉第5個集合中的數,對於集合中的每個數,創建l,r兩個指針,分別指向兩個數組其中一個的頭與另一個的尾。
???若三個數相加>0,則將尾的指針向左移一位。
???若<0,則將頭的指針向右移一位。
???若=0則輸出Yes,直接退出。
???一個比較巧妙的做法,無法理解的話可以畫個圖自行理解理解。
???時間復雜度O(n^3)。
代碼如下:
#include<cstdio> #include<algorithm> #define ll long long #define rint register int using namespace std; const int maxn = 205; int t, n, tot; ll a[6][maxn], b[maxn * maxn], c[maxn * maxn]; ll read(void) { char c; while (c = getchar(), (c < '0' || c > '9') && c != '-'); ll x = 0, y = 1; if (c == '-') y = -1; else x = c - '0'; while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; return x * y; } int main() { t = read(); rint i, j; while (t --) { n = read(); for (i = 1; i <= 5; ++ i) for (j = 1; j <= n; ++ j) a[i][j] = read(); tot = 0; for (i = 1; i <= n; ++ i) //構建第一個數組 for (j = 1; j <= n; ++ j) b[++ tot] = a[1][i] + a[2][j]; tot = 0; for (i = 1; i <= n; ++ i) //構建第二個數組 for (j = 1; j <= n; ++ j) c[++ tot] = a[3][i] + a[4][j]; sort(b + 1, b + 1 + n * n); //排序 sort(c + 1, c + 1 + n * n); int flag = 0; for (i = 1; i <= n; ++ i) { int l = 1, r = n * n; if (flag) break; for (j = 1; j <= n * n * 2; ++ j) { //一共要進行n*n*2次移動 ll val = a[5][i] + b[l] + c[r]; if (val == 0) { flag = 1; break; } else if (val > 0) r --; else l ++; } } if (flag) puts("Yes"); else puts("No"); } return 0; }
hdu4334:Trouble(two pointers, 思維)