GYM 101350 F. Monkeying Around(线段树 or 思维)

Posted zhangbuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GYM 101350 F. Monkeying Around(线段树 or 思维)相关的知识,希望对你有一定的参考价值。

F. Monkeying Around
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

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?

Input

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).

Output

For each test case, output on a line a single integer - the number of monkeys in their seats after all jokes have been said.

Example
Input
1
10 7
3 11 0
3 11 2
5 12 1
8 13 2
7 11 2
10 12 1
9 12 0
Output
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 思维)的主要内容,如果未能解决你的问题,请参考以下文章

F. Monkeying Around 维护点在多少个线段上

GYM 101350 G

CodeForces Gym-101350M

gym-101350M

gym-101350D

gym-101350H