E1. Array and Segments (Easy version)(暴力) && E2. Array and Segments (Hard version)(线段树维护)

题目链接:

E1:http://codeforces.com/contest/1108/problem/E1

E2:http://codeforces.com/contest/1108/problem/E2

题目大意:

给你n个数,然后给你m个区间,每一个区间代表将给定的n个数这个区间内都减去1,每个区间最多使用一次。然后问你使用哪些区间能够使得这n个数中最大数和最小的差值最大?

首先对于E1:这么小的数据不暴力搞啥??直接问枚举就完事了,每一次枚举的时候保持一个数不变,假设当前的数是最大的,然后其他的只要是不包含这个数的区间,都减去,这样就能让最小的那个位置尽可能的小了。

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define inf 0x3f3f3f3f
 5 const int maxn = 400+100;
 6 int a[maxn],b[maxn],sto[maxn];
 7 struct node
 8 {
 9     int le;
10     int ri;
11 } q[maxn];
12 int main()
13 {
14     int n,m;
15     scanf("%d %d",&n,&m);
16     for(int i=1; i<=n; i++)
17     {
18         scanf("%d",&a[i]);
19     }
20     for(int i=1; i<=m; i++)
21     {
22         scanf("%d %d",&q[i].le,&q[i].ri);
23     }
24     int maxx=-inf,id=0;
25     for(int i=1; i<=n; i++)
26     {
27         int t1=-inf,t2=inf;
28         for(int j=1; j<=n; j++)
29         {
30             b[j]=a[j];
31         }
32         for(int j=1; j<=m; j++)
33         {
34             if(i>=q[j].le&&i<=q[j].ri)
35                 continue;
36             for(int k=q[j].le; k<=q[j].ri; k++)
37             {
38                 b[k]-=1;
39             }
40         }
41         for(int j=1; j<=n; j++)
42         {
43             t1=max(t1,b[j]);
44             t2=min(t2,b[j]);
45         }
46         if(t1-t2>maxx)
47         {
48             maxx=t1-t2;
49             id=i;
50         }
51     }
52   //  cout<<m<<endl;
53     printf("%d\n",maxx);
54     int num=0;
55   //  cout<<1<<" "<<num<<endl;
56     for(int i=1; i<=m; i++)
57     {
58         if(id>=q[i].le&&id<=q[i].ri)
59             continue;
60           //  cout<<1<<endl;
61         sto[++num]=i;
62     }
63   //  cout<<2<<" "<<num<<endl;
64     printf("%d\n",num);
65     for(int i=1; i<=num; i++)
66     {
67         if(i==1)
68             printf("%d",sto[i]);
69         else
70             printf(" %d",sto[i]);
71     }
72     printf("\n");
73     return 0;
74 }
View Code

其次对于E2:我们可以寻找最小的数的位置,这个时候为什么不和E1一样去找最大的数的位置呢?因为我们要利用区间的性质,对于每一个节点,我们需要从第一个位置开始。

对于当枚举到第i个节点的时候,需要把包括i的区间都给整上,这个时候求一下最值之差,当枚举到第i+1个节点的时候,我们只需要把不包括第i个节点但是包括第i+1个节点的区间给整上就可以了,这样就能省去很多不必要的操作了。

AC代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 # define ll long long
  4 # define inf 0x3f3f3f3f
  5 # define lson l,m,rt<<1
  6 # define rson m+1,r,rt<<1|1
  7 const int maxn = 1e5+200;
  8 int minn[maxn<<2],maxx[maxn<<2],dif[maxn<<2];
  9 int lazy[maxn<<2];
 10 struct node
 11 {
 12     int le;
 13     int ri;
 14 } edge[500+10];
 15 int sto[maxn];
 16 int ans1,ans2;
 17 vector<int>q1[maxn],q2[maxn];
 18 void up(int rt)
 19 {
 20     minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
 21     maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
 22     dif[rt]=maxx[rt]-minn[rt];// 本来查找最值得差的时候是直接询问到底部的,加了这个就不需要了,学到了!!
 23 }
 24 void build(int l,int r,int rt)
 25 {
 26     if(l==r)
 27     {
 28         int tmp;
 29         scanf("%d",&tmp);
 30         minn[rt]=tmp;
 31         maxx[rt]=tmp;
 32         return ;
 33     }
 34     int m=(l+r)>>1;
 35     build(lson);
 36     build(rson);
 37     up(rt);
 38 }
 39 void down(int rt)
 40 {
 41     if(lazy[rt])
 42     {
 43         lazy[rt<<1]+=lazy[rt];
 44         lazy[rt<<1|1]+=lazy[rt];
 45         minn[rt<<1]+=lazy[rt];
 46         minn[rt<<1|1]+=lazy[rt];
 47         maxx[rt<<1]+=lazy[rt];
 48         maxx[rt<<1|1]+=lazy[rt];
 49         lazy[rt]=0;
 50     }
 51 }
 52 void update(int l,int r,int rt,int L,int R,int p)
 53 {
 54     if(L<=l&&R>=r)
 55     {
 56         minn[rt]+=p;
 57         maxx[rt]+=p;
 58         lazy[rt]+=p;
 59         return ;
 60     }
 61     down(rt);
 62     int m=(l+r)>>1;
 63     if(L<=m)
 64         update(lson,L,R,p);
 65     if(R>m)
 66         update(rson,L,R,p);
 67     up(rt);
 68 }
 69 //int querymax(int l,int r,int rt)
 70 //{
 71 //    if(l==r)
 72 //    {
 73 //        return  maxx[rt];
 74 //    }
 75 //    int t1;
 76 //    down(rt);
 77 //    int m=(l+r)>>1;
 78 //    if(l<=m)querymax(lson);
 79 //    if(r>m)querymax(rson);
 80 //    up(rt);
 81 //}
 82 //void querymin(int l,int r,int rt)
 83 //{
 84 //    if(l==r)
 85 //    {
 86 //        ans2=min(ans2,minn[rt]);
 87 //        return ;
 88 //    }
 89 //    down(rt);
 90 //    int m=(l+r)>>1;
 91 //    querymin(lson);
 92 //   querymin(rson);
 93 //    up(rt);
 94 //}
 95 int main()
 96 {
 97     int n,m,tmp,len;
 98     scanf("%d %d",&n,&m);
 99     build(1,n,1);
100     int ans=-inf,id=0;
101     for(int i=1; i<=m; i++)
102     {
103         scanf("%d %d",&edge[i].le,&edge[i].ri);
104         q1[edge[i].le].push_back(i);
105         q2[edge[i].ri].push_back(i);
106     }
107     for(int i=1; i<=n; i++)
108     {
109         len=q2[i-1].size();
110         for(int j=0; j<len; j++)
111         {
112             tmp=q2[i-1][j];
113             update(1,n,1,edge[tmp].le,edge[tmp].ri,1);
114         }
115         len=q1[i].size();
116         for(int j=0; j<len; j++)
117         {
118             tmp=q1[i][j];
119             update(1,n,1,edge[tmp].le,edge[tmp].ri,-1);
120         }
121         if(ans<dif[1])
122         {
123             ans=dif[1];
124             id=i;
125         }
126     }
127     int num=0;
128    printf("%d\n",ans);
129     for(int i=1; i<=m; i++)
130     {
131         if(edge[i].le<=id&&edge[i].ri>=id)
132         {
133             sto[++num]=i;
134         }
135     }
136     printf("%d\n",num);
137     for(int i=1; i<=num; i++)
138     {
139         if(i==1)
140             printf("%d",sto[i]);
141         else
142             printf(" %d",sto[i]);
143     }
144     printf("\n");
145     return 0;
146 }
View Code

 

posted @ 2019-01-26 22:24  Let_Life_Stop  阅读(679)  评论(0编辑  收藏  举报