E. Two Teams(线段树+链表)
Posted letlifestop
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E. Two Teams(线段树+链表)相关的知识,希望对你有一定的参考价值。
题目链接:
https://codeforces.com/problemset/problem/1154/E
题目大意:
给你n个人和间隔k,两个教练从里面选人。每一次教练选出这个区间里面权值最大的那个学生,然后这个学生往左k个,往右k个,都是这个教练的学生。选完的学生会退出,然后剩余的学生自动补齐。然后问你每一个学生的教练是谁?
具体思路:
一开始没有注意到时自动补齐的,打了一个线段树区间覆盖,wa4
对于这个自动补全,我们可以建立一个链表的形式,保存这个点前面的学生是谁,后面的学生是谁
然后每一次寻找这个区间里面最大的学生编号是哪个,然后这个学生往左往右k个都是当前的教练学生。TLE在37
继续改进,发现有更新操作,也就是说我们可以通过直接判断tree[1]的值就知道当前这个区间里面最大的权值是哪个。然后打一个映射就知道这个学生的编号了,注意指针的跳动。
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define ll long long
4 # define inf 0x3f3f3f3f
5 # define lson l,mid,rt<<1
6 # define rson mid+1,r,rt<<1|1
7 const int maxn = 2e5+100;
8 int pre[maxn],nex[maxn];
9 int a[maxn];
10 int tree[maxn<<2];
11 int lazy[maxn<<2];
12 void down(int rt)
13 {
14 if(lazy[rt])
15 {
16 tree[rt<<1]=0;
17 tree[rt<<1|1]=0;
18 lazy[rt<<1]=1;
19 lazy[rt<<1|1]=1;
20 lazy[rt]=0;
21 }
22 }
23 void up(int rt)
24 {
25 tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
26 }
27 void build(int l,int r,int rt)
28 {
29 if(l==r)
30 {
31 tree[rt]=a[l];
32 return ;
33 }
34 int mid=l+r>>1;
35 build(lson);
36 build(rson);
37 up(rt);
38 }
39 int ans[maxn];
40 int maxx,id;
41 int pos[maxn];
42 //void ask(int l,int r,int rt)
43 //{
44 // if(tree[rt]<maxx)
45 // return ;
46 // if(tree[rt]>maxx)
47 // {
48 // maxx=tree[rt];
49 // }
50 // int mid=l+r>>1;
51 // down(rt);
52 // if(l<=mid)
53 // ask(lson);
54 // if(r>mid)
55 // ask(rson);
56 // up(rt);
57 //}
58 void update(int l,int r,int rt,int L,int R)
59 {
60 if(L<=l&&R>=r)
61 {
62 lazy[rt]=1;
63 tree[rt]=0;
64 return ;
65 }
66 down(rt);
67 int mid=l+r>>1;
68 if(L<=mid)
69 update(lson,L,R);
70 if(R>mid)
71 update(rson,L,R);
72 up(rt);
73 }
74 int main()
75 {
76 int n,k;
77 scanf("%d %d",&n,&k);
78 for(int i=1; i<=n; i++)
79 {
80 scanf("%d",&a[i]);
81 pre[i]=i-1;
82 nex[i]=i+1;
83 pos[a[i]]=i;
84 //cout<<1<<endl;
85 }
86 build(1,n,1);
87 int flag=1,type=1;
88 while(flag)
89 {
90 maxx=tree[1];
91 // ask(1,n,1);
92 if(!maxx)
93 break;
94 id= pos[maxx];
95 ans[id]=type;
96 // cout<<id<<" ";
97 int tmp_l=id;
98 for(int i=1; i<=k; i++)
99 {
100 if(pre[tmp_l]==0)
101 break;
102 ans[pre[tmp_l]]=type;
103 // cout<<pre[tmp_l]<<" ";
104 tmp_l=pre[tmp_l];
105 }
106 int tmp_r=id;
107 for(int i=1; i<=k; i++)
108 {
109 if(nex[tmp_r]==n+1)
110 break;
111 ans[nex[tmp_r]]=type;
112 // cout<<pre[tmp_l]<<" ";
113 tmp_r=nex[tmp_r];
114 }
115 update(1,n,1,tmp_l,tmp_r);
116 int tmp1=nex[tmp_r];
117 int tmp2=pre[tmp_l];
118 pre[tmp1]=tmp2;
119 nex[tmp2]=tmp1;
120 type=(type==1?2:1);
121 }
122 for(int i=1; i<=n; i++)
123 {
124 printf("%d",ans[i]);
125 }
126 printf("\n");
127 return 0;
128 }
以上是关于E. Two Teams(线段树+链表)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 292 E. Copying Data (线段树)
CodeForces915 E. Physical Education Lessons 线段树
Codeforces Round #603 (Div. 2) E. Editor 线段树