FJ省队集训DAY3 T1

思路:我们考虑如果取掉一个部分,那么能影响到最优解的只有离它最近的那两个部分。

因此我们考虑堆维护最小的部分,离散化离散掉区间,然后用线段树维护区间有没有雪,最后用平衡树在线段的左右端点上面维护最小的id

我讲的貌似不是很清楚。。

还有,蜜汁80分,打死也改不出来。。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<algorithm>
  6 struct node{
  7     int l,r,cnt,id;
  8 }a[1200005];
  9 struct segment{
 10     int l,r,v;
 11     segment(){}
 12     segment(int l0,int r0,int v0):l(l0),r(r0),v(v0){}
 13 }t[5000005];
 14 struct treap{
 15     int l,r,rnd,v;
 16 }tt[5000005];
 17 int tag[5000005],vis[1000005],Tcase;
 18 int len[1000005],next[1500005],before[1500005],pos[1000005],heap[1000005];
 19 int o[1500005],p[1000005],sz,Id[1000005],pls[1500005];
 20 int c[2500005],Cnt,sb,rt1[1500005],rt2[1500005],all[500006];
 21 int tot,n,Len;
 22 int read(){
 23     int t=0,f=1;char ch=getchar();
 24     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
 25     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
 26     return t*f;
 27 }
 28 bool cmp(node a,node b){
 29     return a.r-a.l<b.r-b.l;
 30 }
 31 void push_up(int x){
 32     while (x>1){
 33         if (len[x/2]>len[x]||(len[x/2]==len[x]&&heap[x/2]>heap[x])) std::swap(len[x/2],len[x]),std::swap(heap[x/2],heap[x]),std::swap(pos[heap[x]],pos[heap[x/2]]);
 34         else break;
 35         x/=2;
 36     }
 37 }
 38 void push_down(int x){
 39     int j;
 40     while (x*2<=tot){
 41         if (x*2==tot) j=2*x;
 42         else if (len[2*x]<len[2*x+1]||(len[2*x]==len[2*x+1]&&heap[2*x]<heap[2*x+1])) j=2*x;
 43         else j=2*x+1;
 44         if (len[x]>len[j]||(len[x]==len[j]&&heap[j]<heap[x])){
 45             std::swap(len[x],len[j]);
 46             std::swap(heap[x],heap[j]);
 47             std::swap(pos[heap[x]],pos[heap[j]]);
 48         }
 49         x=j;
 50     }
 51 }
 52 void add_heap(int x,int v){
 53     heap[++tot]=x;
 54     len[tot]=v;
 55     pos[x]=tot;
 56     push_up(tot);
 57 }
 58 void delete_heap(int x){
 59     int Pos=pos[x];
 60     heap[Pos]=heap[tot];
 61     len[Pos]=len[tot];
 62     pos[heap[tot]]=Pos;
 63     tot--;
 64     push_down(Pos);
 65 }
 66 void modify_heap(int x,int y){
 67     int Pos=pos[x];
 68     len[Pos]=y;
 69     push_up(Pos);
 70 }
 71 void build(int k,int l,int r){
 72     if (l==r){
 73         t[k].v=o[l];
 74         t[k].l=t[k].r=l;
 75         return;
 76     }
 77     int mid=(l+r)>>1;
 78     build(k*2,l,mid);
 79     build(k*2+1,mid+1,r);
 80     t[k].v=t[k*2].v+t[k*2+1].v;
 81     t[k].l=std::min(t[k*2].l,t[k*2+1].l);
 82     t[k].r=std::max(t[k*2].r,t[k*2+1].r);
 83 }
 84 void pushdown(int k,int l,int r){
 85     if (!tag[k]||l==r) return;
 86     tag[k]=0;
 87     t[k*2].v=t[k*2+1].v=0;
 88     tag[k*2]=tag[k*2+1]=1;
 89     t[k*2].l=t[k*2+1].l=Len+1;
 90     t[k*2].r=t[k*2+1].r=0;
 91 }
 92 void modify(int k,int l,int r,int x,int y){
 93     if (l>r) return;
 94     if (l>y||r<x) return;
 95     pushdown(k,l,r);
 96     if (l==x&&r==y){
 97         tag[k]=1;
 98         t[k].l=Len+1;
 99         t[k].r=0;
100         t[k].v=0;
101         pushdown(k,l,r);
102         return;
103     }
104     int mid=(l+r)>>1;
105     if (y<=mid) modify(k*2,l,mid,x,y);
106     else
107     if (x>mid) modify(k*2+1,mid+1,r,x,y);
108     else modify(k*2,l,mid,x,mid),modify(k*2+1,mid+1,r,mid+1,y);
109     t[k].v=t[k*2].v+t[k*2+1].v;
110     t[k].l=std::min(t[k*2].l,t[k*2+1].l);
111     t[k].r=std::max(t[k*2].r,t[k*2+1].r);
112 }
113 segment query(int k,int l,int r,int x,int y){
114     if (x>y) return segment(x,y,0);
115     pushdown(k,l,r);
116     if (l==x&&r==y){
117         return segment(t[k].l,t[k].r,t[k].v);
118     }
119     int mid=(l+r)>>1;
120     if (y<=mid) return query(k*2,l,mid,x,y);
121     else
122     if (x>mid) return query(k*2+1,mid+1,r,x,y);
123     else{
124     segment t1=query(k*2,l,mid,x,mid);
125     segment t2=query(k*2+1,mid+1,r,mid+1,y);
126     return segment(std::min(t1.l,t2.l),std::max(t1.r,t2.r),t1.v+t2.v);
127     }
128 }
129 int find(int x){
130     int l=1,r=p[0];
131     while (l<=r){
132         int mid=(l+r)>>1;
133         if (p[mid]==x) return Id[mid];
134         if (p[mid]<x) l=mid+1;
135         else r=mid-1;
136     }
137 }
138 void sbpianfen1(){
139     int T=n;
140     for (int i=1;i<=n;i++)
141      a[i].l=read(),a[i].r=read(),a[i].id=i,a[i].cnt=a[i].r-a[i].l+1,add_heap(i,a[i].r-a[i].l+1),p[++p[0]]=a[i].l,p[++p[0]]=a[i].r;
142     std::sort(p+1,p+1+p[0]);int j=1;
143     for (int i=2;i<=p[0];i++)
144      if (p[i]!=p[j]) p[++j]=p[i];p[0]=j;
145
146     for (int i=1;i<=p[0];i++)
147      if (p[i]!=p[i-1]){
148         o[++sz]=p[i]-p[i-1]-1;
149         o[++sz]=1;
150         Id[i]=sz;
151      }
152     Len=sz;
153     for (int i=1;i<=n;i++)
154      a[i].l=find(a[i].l),a[i].r=find(a[i].r);
155     build(1,1,Len);
156     a[n+1].cnt=0x7fffffff;
157     while (T--){
158         int mn=n+1;
159         for (int i=n;i>=1;i--)
160          if (a[i].cnt<=a[mn].cnt&&!vis[i]) mn=i;
161         printf("%d\n",mn);vis[mn]=1;
162         modify(1,1,Len,a[mn].l,a[mn].r);
163         for (int i=1;i<=n;i++){
164           segment t1=query(1,1,Len,a[i].l,a[i].r);
165           a[i].cnt=t1.v;
166         }
167     }
168 }
169 void lturn(int &k){
170     if (!k) return;
171     int TT=tt[k].r;tt[k].r=tt[TT].l;tt[TT].l=k;k=TT;
172 }
173 void rturn(int &k){
174     if (!k) return;
175     int TT=tt[k].l;tt[k].l=tt[TT].r;tt[TT].r=k;k=TT;
176 }
177 void insert(int &k,int v){
178     if (!k){
179         if (Cnt) k=c[Cnt--];else k=++sb;
180         tt[k].l=tt[k].r=0;tt[k].rnd=rand();
181         tt[k].v=v;
182         all[v]++;
183         return;
184     }
185     if (tt[k].v==v) {all[v]++;return;}
186     if (tt[k].v<v){
187         insert(tt[k].r,v);
188         if (tt[tt[k].r].rnd<tt[k].rnd) lturn(k);
189     }else{
190         insert(tt[k].l,v);
191         if (tt[tt[k].l].rnd<tt[k].rnd) rturn(k);
192     }
193 }
194 void del(int &k,int v){
195     if (!k) return;
196     if (tt[k].v==v){
197         if (tt[k].l*tt[k].r==0){
198             c[++Cnt]=k;
199             k=tt[k].l+tt[k].r;
200             all[v]--;
201             return;
202         }
203         if (tt[tt[k].l].rnd<tt[tt[k].r].rnd){
204             rturn(k);
205             del(k,v);
206         }else{
207             lturn(k);
208             del(k,v);
209         }
210         return;
211     }
212     if (tt[k].v<v) del(tt[k].r,v);
213     else del(tt[k].l,v);
214 }
215 int find_treap(int k){
216     while (tt[k].l!=0) k=tt[k].l;
217     return tt[k].v;
218 }
219 bool findit(int k,int x){
220     if (!k) return 0;
221     if (tt[k].v==x) return 1;
222     else if (tt[k].v<x) return findit(tt[k].r,x);
223     else return findit(tt[k].l,x);
224 }
225 void Gwork(){
226     Tcase=Tcase;
227 }
228 void updata(int x,int id){
229     if (id==1) x=pls[find_treap(rt1[a[x].l])];
230     else if (id==2) x=pls[find_treap(rt2[a[x].r])];
231     if (a[x].l>a[x].r) return;
232     segment t1=query(1,1,Len,a[x].l,a[x].r);
233     a[x].cnt=t1.v;
234     if (a[x].id==51612&&(a[x].l==206449||a[x].r==206449)) Gwork();
235     del(rt1[a[x].l],a[x].id);
236     del(rt2[a[x].r],a[x].id);
237     a[x].l=t1.l;
238     a[x].r=t1.r;
239     insert(rt1[a[x].l],a[x].id);
240     insert(rt2[a[x].r],a[x].id);
241     modify_heap(a[x].id,a[x].cnt);
242 }
243 void sbpianfen3(){
244     for (int i=1;i<=n;i++)
245      a[i].l=read(),a[i].r=read(),a[i].cnt=a[i].r-a[i].l+1,a[i].id=i,add_heap(i,a[i].r-a[i].l+1),p[++p[0]]=a[i].l,p[++p[0]]=a[i].r;
246     std::sort(p+1,p+1+p[0]);int j=1;
247     for (int i=2;i<=p[0];i++)
248      if (p[i]!=p[j]) p[++j]=p[i];p[0]=j;
249     for (int i=1;i<=p[0];i++)
250      if (p[i]!=p[i-1]){
251         o[++sz]=p[i]-p[i-1]-1;
252         o[++sz]=1;
253         Id[i]=sz;
254      }
255     Len=sz;
256     for (int i=1;i<=n;i++)
257      a[i].l=find(a[i].l),a[i].r=find(a[i].r),insert(rt1[a[i].l],i),insert(rt2[a[i].r],i);
258     for (int i=1;i<=n;i++)
259      pls[a[i].id]=i;
260     for (int i=2;i<=n;i++) before[i]=i-1;
261     for (int i=1;i<n;i++) next[i]=i+1;
262     int T=n;
263     build(1,1,Len);
264     while (T--){
265         Tcase++;
266         int x=heap[1];printf("%d\n",x);
267         delete_heap(x);
268         if (a[x].l>a[x].r){
269             int t1=before[pls[x]],t2=next[pls[x]];
270             next[t1]=t2;
271             before[t2]=t1;
272             continue;
273         }
274         if (Tcase==2872) Gwork();
275         modify(1,1,Len,a[pls[x]].l,a[pls[x]].r);
276         if (before[pls[x]]) updata(before[pls[x]],1);
277         if (next[pls[x]]) updata(next[pls[x]],2);
278         int t1=before[pls[x]],t2=next[pls[x]];
279         next[t1]=t2;
280         before[t2]=t1;
281     }
282 }
283 int main(){
284     Len=read();n=read();
285     if (n<=1000) {sbpianfen1();fclose(stdin);fclose(stdout);return 0;}
286     sbpianfen3();
287     fclose(stdin);fclose(stdout);
288     return 0;
289 }
时间: 2024-10-23 19:02:00

FJ省队集训DAY3 T1的相关文章

FJ省队集训DAY1 T1

题意:有一堆兔子,还有一个r为半径的圆,要求找到最大集合满足这个集合里的兔子两两连边的直线不经过圆. 思路:发现如果有两个点之间连边不经过圆,那么他们到圆的切线会构成一段区间,那么这两个点的区间一定会有交集,形如s0 s1 e0 e1 同样的,如果是n个点,那就是s0 s1 s2..sn e0 e1 e2.. en 因此,我们枚举那个起始点,然后对于其他点我们按照s排序,对于e做最长上升子序列即可.时间复杂度O(n^2 logn) 1 #include <cstdio> 2 #include

FJ省队集训DAY2 T1

思路:转换成n条三维空间的直线,求最大的集合使得两两有交点. 有两种情况:第一种是以某2条直线为平面,这时候只要统计这个平面上有几条斜率不同的直线就可以了 还有一种是全部交于同一点,这个也只要判断就可以了. 然后我并不能改出来,wa了好多个点 WA的程序: 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm&

FJ省队集训DAY5 T1

思路:考试的时候打了LCT,自以为能过,没想到只能过80.. 考完一想:lct的做法点数是100W,就算是nlogn也会T. 讲一下lct的做法把:首先如果一条边连接的两个点都在同一个联通块内,那么这条边对答案没有影响,可以忽略,因此,问题变成了每次询问两个点中路径上权值最大的边(这里的权值我们令它为加入这条边的时间),边我们用一个点连接两个端点来表示. 正解:由于是无根树,因此我们用并查集按秩合并,每次把小的加到大的里面去,询问的时候暴力走lct查找最大即可. 1 #include<cstdi

FJ省队集训DAY4 T1

直接上题解 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define ll long long 7 const int Mod=1000000009,N=3000; 8 ll jc[N+10],jcny[N+10],jcnys[N+10],K[N+10],p[N+10],f[N+10];

FJ省队集训DAY3 T2

思路:如果一个DAG要的路径上只要一条边去切掉,那么要怎么求?很容易就想到最小割,但是如果直接做最小割会走出重复的部分,那我们就这样:反向边设为inf,这样最小割的时候就不会割到了,判断无解我们直接用tarjan 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #define ll long

2015湖南省队集训DAY3——Light

Light [问题描述] "若是万一琪露诺(俗称 rhl)进行攻击,什么都好,冷静地回答她的问题来吸引 对方表现出兴趣的话,那就慢慢地反问.在她考虑答案的时候,趁机逃吧.就算是很简 问题,她一定也答不上来." --<上古之魔书> 天空中出现了许多的北极光,这些北极光组成了一个长度为n的正整数数列 a[i],远 魔书上记载到:2 个位置的 graze 值为两者位置差与数值差的和: graze(x,y)=|x-y|+|a[x]-a[y]|. 要想破解天罚,就必须支持 2种操作(

FJ省队集训DAY2 T2

思路:我们可以考虑三角剖分,这样问题就变成考虑三角形的选取概率和三角形内有多少个点了. 先用树状数组预处理出三角剖分的三角形中有多少个点,然后用线段树维护,先用原点极角排序,然后枚举i,再以i极角排序,此时线段树的作用就来了,每次到一个询问的教室点,我们就在线段树里面查找之前的概率,统计贡献即可. 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #

bzoj4171 or 省队集训day3 chess: Rhl的游戏

[题目描述] RHL最近迷上一个小游戏:Flip it.游戏的规则很简单,在一个N*M的格子上,有一些格子是黑色,有一些是白色.每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少与该格子有一条公共边的格子),黑变白,白变黑. RHL希望把所有格子都变成白色的.不幸的是,有一些格子坏掉了,无法被按下.这时,它可以完成游戏吗? [输入格式] 第一行一个整数T,表示T组数据. 每组数据开始于三个整数n,m,k,分别表示格子的高度和宽度.坏掉格子的个数.接下来的n行,每行一个长度m

FJ省队集训DAY4 T2

XXX 1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<vector> 7 using namespace std; 8 typedef unsigned long long ll; 9 ll a,mod=1,L=1; 10 ll tr[4],b[4],tmp[4