1. POJ2259:据说很容易的队列题(事实好像也是emmm,抛开流氓一样无赖的输入输出格式),把element变index,team number变value比其正常相反的套路要好得多。
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long ll; 15 #define MS(x) memset(x,0,sizeof(x)); 16 #define inf 0x3f3f3f3f 17 18 const int maxn = 1e6 + 10; 19 20 int team[maxn]; 21 22 int main() 23 { 24 int t; 25 int count = 1; 26 while (scanf("%d", &t) && t != 0) 27 { 28 queue<int> q; 29 queue<int> tq[1005]; 30 MS(team); 31 printf("Scenario #%d\n", count); 32 count++; 33 for (int i = 1; i <= t; i++) 34 { 35 int times; 36 scanf("%d", ×); 37 for (int j = 1; j <= times; j++) 38 { 39 int element; 40 scanf("%d", &element); 41 team[element] = i; 42 } 43 } 44 char implement[200]; 45 while (scanf("%s", implement) != EOF) 46 { 47 if (implement[0] == 'S') 48 break; 49 else if (implement[0] == 'E') 50 { 51 int numb; 52 scanf("%d", &numb); 53 if (tq[team[numb]].empty()) 54 q.push(team[numb]); 55 tq[team[numb]].push(numb); 56 } 57 else if (implement[0] == 'D') 58 { 59 if (!tq[q.front()].empty()) 60 { 61 printf("%d\n", tq[q.front()].front()); 62 tq[q.front()].pop(); 63 } 64 else 65 { 66 q.pop(); 67 if (!tq[q.front()].empty()) 68 { 69 printf("%d\n", tq[q.front()].front()); 70 tq[q.front()].pop(); 71 } 72 } 73 } 74 } 75 printf("\n"); 76 } 77 return 0; 78 }
2. 洛谷P2827:这道题是2016NOIP的题(看到一个初三学生的压力准大二阿萌感到。。。罢了罢了)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long ll; 15 #define MS(x) memset(x,0,sizeof(x)) 16 #define inf 0x3f3f3f3f 17 const int maxn = 1e5 + 10; 18 19 priority_queue<int> rowinsect;//我就说蚯蚓是昆虫咋地啦 20 queue<int> insect1; 21 queue<int> insect2; 22 23 int main() 24 { 25 int n, m, q, u, v, t; 26 scanf("%d %d %d %d %d %d", &n, &m, &q, &u, &v, &t); 27 double p = (double)u / v; 28 int lenth; 29 for (int i = 1; i <= n; i++) 30 { 31 scanf("%d", &lenth); 32 rowinsect.push(lenth); 33 } 34 int deta = 0; 35 for (int j = 1; j <= m; j++) 36 { 37 int lh, rh, mark0 = -0x7fffffff, mark1 = -0x7fffffff, mark2 = -0x7fffffff; 38 int longest = -0x7fffffff; 39 if (!rowinsect.empty()) 40 longest = max(longest, rowinsect.top()), mark0 = rowinsect.top(); 41 if (!insect1.empty()) 42 longest = max(longest, insect1.front()), mark1 = insect1.front(); 43 if (!insect2.empty()) 44 longest = max(longest, insect2.front()), mark2 = insect2.front(); 45 if (longest == mark0) 46 rowinsect.pop(); 47 else if (longest == mark1) 48 insect1.pop(); 49 else 50 insect2.pop(); 51 longest += deta; 52 int pl = p * longest; 53 lh = pl - q - deta; 54 rh = longest - pl - q - deta; 55 deta += q; 56 if (j >= t && j % t == 0) 57 printf("%d ", longest); 58 insect1.push(lh); 59 insect2.push(rh); 60 } 61 printf("\n"); 62 for (int i = 1; !rowinsect.empty() || !insect1.empty() || !insect2.empty(); i++) 63 { 64 int mark0 = -0x7fffffff, mark1 = -0x7fffffff, mark2 = -0x7fffffff; 65 int longest = -0x7fffffff; 66 if (!rowinsect.empty()) 67 longest = max(longest, rowinsect.top()), mark0 = rowinsect.top(); 68 if (!insect1.empty()) 69 longest = max(longest, insect1.front()), mark1 = insect1.front(); 70 if (!insect2.empty()) 71 longest = max(longest, insect2.front()), mark2 = insect2.front(); 72 if (i >= t && i % t == 0) 73 printf("%d ", longest + deta); 74 if (longest == mark0) 75 rowinsect.pop(); 76 else if (longest == mark1) 77 insect1.pop(); 78 else 79 insect2.pop(); 80 } 81 return 0; 82 }
这里有两个点,第一个每切一次是需要将所有元素+q,用遍历太TLE了所以我们就用了一个deta来储存q值得累积度,和我想的一样就是其他不变单独减那两条被剪的,在后面再加回来。第二点就是如果单独用一个优先队列,那么由于二叉堆的劣根性我们还是会在某些数据上TLE,所以题解是推荐再用两个数组/普通队列进行维护,理论基础(不需要优先队列自动排序的理由)是每次先剪的蚯蚓分成的两半一定比后减的两半各比例分别都要长,所以把这两个比例用两个数组/队列存起来,得到的数组/队列本身就具备了单调性,所以一次弹出将三个top()比较也不会有问题啦。
(洛谷还有其他解法到时看心情(我觉得以后有缘吧)看咯)
3. BZOJ 2457:双端队列,(但事实不需要用队列,只是解题需要通晓队列的知识从而得出规律)(最后还是顺着点拨用自己的思路杠出来了——所以和网上标准题解不同滴!)
1 #pragma warning (disable:4996) 2 #include <algorithm> 3 #include <iostream> 4 #include <iomanip> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <queue> 9 #include <stack> 10 #include <cmath> 11 #include <map> 12 #include <set> 13 using namespace std; 14 typedef long long ll; 15 #define MS(x) memset(x,0,sizeof(x)) 16 #define inf 0x3f3f3f3f 17 const int maxn = 2e5 + 10; 18 19 pair<int, int> vi[maxn];//value and index 20 int mx[maxn]; 21 int mi[maxn]; 22 23 bool cmp(pair<int, int>v1, pair<int, int>v2) 24 { 25 return v1.first == v2.first ? (v1.second < v2.second) : (v1.first < v2.first); 26 } 27 28 int main() 29 { 30 int N; 31 scanf("%d", &N); 32 for (int i = 1; i <= N; i++) 33 scanf("%d", &vi[i].first), vi[i].second = i; 34 sort(vi + 1, vi + N + 1, cmp);//由此得到关于index的变化曲线,根据规律(什么规律?自己找去)得出极小值的个数就是双端队列的个数 35 int cnt = 0; 36 for (int i = 1; i <= N; i++) 37 { 38 if (i == 1 || vi[i].first != vi[i - 1].first) 39 { 40 mx[cnt] = vi[i - 1].second;//mx表示相同value时index最大的那一个 41 mi[++cnt] = vi[i].second;//mi表示value相同时index最小的那一个 42 } 43 } 44 mx[cnt] = vi[N].second; 45 int ans = 1; 46 bool decrease = true;//判断当前为递增/递减(初始为递减) 47 int now = 0x7f7f7f7f;//当前值 48 for (int i = 1; i <= cnt; i++)//tips:i<cnt 49 { 50 if (decrease) 51 { 52 if (now > mx[i]) 53 now = mi[i]; 54 else 55 now = mx[i], decrease = false; 56 } 57 else 58 { 59 if (now > mi[i]) 60 now = mi[i], decrease = true, ans++;//以再一次递减为标志ans+1 61 else 62 now = mx[i]; 63 } 64 } 65 printf("%d", ans); 66 return 0; 67 }
4.