GYM 101350 F. Monkeying Around(线段树 or 思维)
Posted zhangbuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GYM 101350 F. Monkeying Around(线段树 or 思维)相关的知识,希望对你有一定的参考价值。
When the monkey professor leaves his class for a short time, all the monkeys go bananas. N monkeys are lined up sitting side by side on their chairs. They each have the same joke book. Before the professor returns, M jokes were heard.
Each of the M jokes are said in the order given and have the following properties:
xi - position of the monkey who said it.
li – index of the joke in the book.
ki – volume the monkey says that joke.
When the monkey at position xi says the joke li, all monkeys at a distance less than or equal to ki from that monkey (including the monkey who said the joke) will fall off their chairs in laughter if they have never heard the joke li before.
If the joke li has been heard anytime during the past before, and the monkey hears it again, then he will sit back up in his chair.
A monkey can fall off his chair more than once (every time he hears a new joke), and if he is already on the ground and hears a new joke, he will stay on the ground.
Can you figure out how many monkeys will be in their seats by the time the professor comes back?
The first line of input is T – the number of test cases.
The first line of each test case is N, M (1 ≤ N ≤ 105) (1 ≤ M ≤ 105) – the number of monkeys in the class, and the number of jokes said before the professor returns.
The next M lines contain the description of each joke: xi, li, ki (1 ≤ xi ≤ N) (1 ≤ li ≤ 105) (0 ≤ ki ≤ N).
For each test case, output on a line a single integer - the number of monkeys in their seats after all jokes have been said.
1
10 7
3 11 0
3 11 2
5 12 1
8 13 2
7 11 2
10 12 1
9 12 0
3
我开始傻×的把操作存了起来,然后按笑话的种类排序,可是后来发现不能这么做啊,室友先后顺序的!!
因为每一只猴子的最后的状态要看他最后一次听到的笑话是什么,然后再看这个笑话听到了几次若果是==1,就从椅子下来。
第一步求每一只猴子最后听到那种笑话:首先可以线段树,然后也可以set求
第二部 求每一只猴子最后一次听到的笑话的种类的数量
有两种方法!
1: for每一只猴子,然后在猴子的位置上对每种笑话进行查分,num【i】 保存每种颜色的数量
2:for每一个笑话的种类,在for在这个种类上的猴子并查询
第一种码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <cmath> 7 #include <map> 8 #include <set> 9 #include <stack> 10 #include <queue> 11 #include <vector> 12 #include <bitset> 13 #include <functional> 14 15 using namespace std; 16 17 #define LL long long 18 const int INF = 0x3f3f3f3f; 19 const int maxn = 1e5 + 10; 20 21 int n, m, x, y, z; 22 int a[maxn << 2], lazy[maxn << 2]; 23 int sum[maxn]; 24 vector<pair<int, int> > g1[maxn]; 25 vector<int>g2[maxn]; 26 27 void build(int k, int l, int r) 28 { 29 a[k] = lazy[k] = 0; 30 if (l == r) return; 31 int mid = (l + r) / 2; 32 build(k << 1, l, mid); 33 build(k << 1 | 1, mid + 1, r); 34 } 35 36 void pushDown(int k) 37 { 38 a[k << 1] = a[k << 1 | 1] = lazy[k]; 39 lazy[k << 1] = lazy[k << 1 | 1] = lazy[k]; 40 lazy[k] = 0; 41 } 42 43 void update(int k, int l, int r, int ll, int rr, int val) 44 { 45 if (ll <= l && r <= rr) 46 { 47 a[k] = lazy[k] = val; 48 return; 49 } 50 int mid = (l + r) / 2; 51 if (lazy[k]) pushDown(k); 52 if (ll <= mid) update(k << 1, l, mid, ll, rr, val); 53 if (rr > mid) update(k << 1 | 1, mid + 1, r, ll, rr, val); 54 } 55 56 int get(int k, int l, int r, int p) 57 { 58 if (l == r) return a[k]; 59 int mid = (l + r) / 2; 60 if (lazy[k]) pushDown(k); 61 if (p <= mid) return get(k << 1, l, mid, p); 62 return get(k << 1 | 1, mid + 1, r, p); 63 } 64 65 int lowbit(int k) 66 { 67 return k & -k; 68 } 69 70 void update(int k, int val) 71 { 72 for (int i = k; i < maxn; i += lowbit(i)) 73 sum[i] += val; 74 } 75 76 int getsum(int k) 77 { 78 int ans = 0; 79 for (int i = k; i; i -= lowbit(i)) 80 ans = ans + sum[i]; 81 return ans; 82 } 83 84 int main() 85 { 86 int t; 87 scanf("%d", &t); 88 while (t--) 89 { 90 scanf("%d%d", &n, &m); 91 for (int i = 0; i < maxn; i++) 92 { 93 g1[i].clear(); 94 g2[i].clear(); 95 } 96 build(1, 1, n); 97 for (int i = 1; i <= m; i++) 98 { 99 scanf("%d%d%d", &x, &y, &z); 100 int L = max(1, x - z); 101 int R = min(n, x + z); 102 update(1, 1, n, L, R, y); 103 g1[y].push_back(make_pair(L, R)); 104 } 105 for (int i = 1; i <= n; i++) 106 { 107 int k = get(1, 1, n, i); 108 g2[k].push_back(i); 109 } 110 int ans = g2[0].size(); 111 for (int i = 1; i < maxn; i++) 112 { 113 int Size1 = g1[i].size(), Size2 = g2[i].size(); 114 if (Size1 == 0 || Size2 == 0) continue; 115 for (int j = 0; j < Size1; j++) 116 { 117 pair<int, int>p = g1[i][j]; 118 update(p.first, 1); 119 update(p.second + 1, -1); 120 } 121 for (int j = 0; j < Size2; j++) 122 { 123 int p = g2[i][j]; 124 if (getsum(p) >= 2) ans++; 125 } 126 for (int j = 0; j < Size1; j++) 127 { 128 pair<int, int>p = g1[i][j]; 129 update(p.first, -1); 130 update(p.second + 1, 1); 131 } 132 } 133 printf("%d ", ans); 134 } 135 return 0; 136 }
第二种:
1 #include<cstdio> 2 #include<iostream> 3 #include<set> 4 #include<vector> 5 #include<cstring> 6 #include<string> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=100000+10; 10 set<int> s; 11 vector<int> G[maxn]; 12 int n,m,num[maxn],type[maxn]; 13 int main(void) 14 { 15 int xx,ll,kk,T,ans; 16 cin>>T; 17 while(T--) 18 { 19 ans=0; 20 for(int i=0;i<maxn;i++) 21 G[i].clear(); 22 s.clear(); 23 memset(num,0,sizeof(num)); 24 scanf("%d%d",&n,&m); 25 for(int ii=1;ii<=m;ii++) 26 { 27 scanf("%d%d%d",&xx,&ll,&kk); 28 type[ii]=ll; 29 int lend=max(1,xx-kk); 30 int rend=min(n,xx+kk); 31 G[lend].push_back(ii); 32 G[rend+1].push_back(-ii); 33 } 34 for(int i=1;i<=n;i++) 35 { 36 for(auto it:G[i]) 37 { 38 if(it>0)//This is the begin position for a joke 39 { 40 s.insert(it); 41 num[type[it]]++; 42 } 43 else 44 { 45 s.erase(-it); 46 num[type[-it]]--; 47 } 48 } 49 if(s.empty()) 50 ans++;//important! No jokes at all 51 else 52 { 53 auto it=s.end(); 54 it--; 55 if(num[type[*it]]>1) 56 ans++; 57 } 58 } 59 cout<<ans<<endl; 60 } 61 return 0; 62 }
1 #include<cstdio> 2 #include<iostream> 3 #include<set> 4 #include<vector> 5 #include<cstring> 6 #include<string> 7 #include<algorithm> 8 using namespace std; 9 const int maxn=100000+10; 10 set<int> s; 11 vector<int> G[maxn]; 12 int n,m,num[maxn],type[maxn]; 13 int main(void) 14 { 15 int xx,ll,kk,T,ans; 16 cin>>T; 17 while(T--) 18 { 19 ans=0; 20 for(int i=0;i<maxn;i++) 21 G[i].clear(); 22 s.clear(); 23 memset(num,0,sizeof(num)); 24 scanf("%d%d",&n,&m); 25 for(int ii=1;ii<=m;ii++) 26 { 27 scanf("%d%d%d",&xx,&ll,&kk); 28 type[ii]=ll; 29 int lend=max(1,xx-kk); 30 int rend=min(n,xx+kk); 31 G[lend].push_back(ii); 32 G[rend+1].push_back(-ii); 33 } 34 for(int i=1;i<=n;i++) 35 { 36 for(auto it:G[i]) 37 { 38 if(it>0)//This is the begin position for a joke 39 { 40 s.insert(it); 41 num[type[it]]++; 42 } 43 else 44 { 45 s.erase(-it); 46 num[type[-it]]--; 47 } 48 } 49 if(s.empty()) 50 ans++;//important! No jokes at all 51 else 52 { 53 auto it=s.end(); 54 it--; 55 if(num[type[*it]]>1) 56 ans++; 57 } 58 } 59 cout<<ans<<endl; 60 } 61 return 0; 62 }
以上是关于GYM 101350 F. Monkeying Around(线段树 or 思维)的主要内容,如果未能解决你的问题,请参考以下文章