【分块】【常数优化】【Orz faebdc】洛谷 P1083 NOIP2012提高组 借教室

分块90分。 By AutSky_JadeK 【重点在下面】

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 #define N 1000001
 5 #define INF 2147483647
 6 #define min(a,b) (((a)<(b))?(a):(b))
 7 int n,m,a[N],sum,sz,l[8001],r[8001],minv[8001],delta[8001],num[N],x,y,v;
 8 int ans,re2;
 9 int Res;char C;
10 inline int G()
11 {
12     Res=0;C='*';
13     while(C<'0'||C>'9')C=getchar();
14     while(C>='0'&&C<='9'){Res=Res*10+(C-'0');C=getchar();}
15     return Res;
16 }
17 void makeblock()
18 {
19     sz=(int)sqrt((double)n*0.1); if(!sz) sz=1;
20     for(sum=1;sum*sz<n;sum++)
21       {
22         l[sum]=r[sum-1]+1; r[sum]=sum*sz;
23         minv[sum]=INF;
24         for(int i=l[sum];i<=r[sum];i++) {minv[sum]=min(minv[sum],a[i]); num[i]=sum;}
25       }
26     l[sum]=r[sum-1]+1; r[sum]=n;
27     minv[sum]=INF;
28     for(int i=l[sum];i<=r[sum];i++) {minv[sum]=min(minv[sum],a[i]); num[i]=sum;}
29 }
30 inline void work(const int &L,const int &R)
31 {
32     minv[num[L]]=INF;
33     for(int i=L;i<=R;i++) a[i]-=v;
34     for(int i=l[num[L]];i<=r[num[L]];i++) minv[num[L]]=min(minv[num[L]],a[i]);
35 }
36 inline void update()
37 {
38     if(num[x]==num[y]) work(x,y);
39     else
40       {
41         work(x,r[num[x]]); work(l[num[y]],y);
42         for(int i=num[x]+1;i<num[y];i++) delta[i]-=v;
43       }
44 }
45 inline int query()
46 {
47     ans=INF;
48     if(num[x]==num[y]) {for(int i=x;i<=y;i++) ans=min(ans,a[i]+delta[num[x]]); }
49     else
50       {
51         for(int i=x;i<=r[num[x]];i++) ans=min(ans,a[i]+delta[num[x]]);
52         for(int i=num[x]+1;i<num[y];i++) ans=min(ans,minv[i]+delta[i]);
53         for(int i=l[num[y]];i<=y;i++) ans=min(ans,a[i]+delta[num[y]]);
54       } return ans;
55 }
56 int main()
57 {
58     n=G(); m=G();
59     for(int i=1;i<=n;i++) a[i]=G();
60     makeblock();
61     for(int i=1;i<=m;i++)
62       {
63         v=G(); x=G(); y=G();
64         if(query()<v)
65           {
66             printf("-1
%d
",i);
67             return 0;
68           }
69         else update();
70       }
71     puts("0");
72     return 0;
73 }

分块 常数优化 100分。 By faebdc 金牌爷の力Orzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 #define N 1000001
 5 #define INF 2147483647
 6 int n,m,a[N],sum,sz,hf,l[3001],r[3001],minv[3001],delta[3001],num[N],x,y,v;
 7 int ans,re2;
 8 int Res;char C;
 9 inline int G()
10 {
11     Res=0;C='*';
12     while(C<'0'||C>'9')C=getchar();
13     while(C>='0'&&C<='9'){Res=(Res<<3)+(Res<<1)+C-'0';C=getchar();}
14     return Res;
15 }
16 void makeblock()
17 {
18     sz=(int)sqrt((double)n*0.125); if(!sz) sz=1;
19     hf=sz>>1;
20     for(sum=1;sum*sz<n;sum++)
21       {
22         l[sum]=r[sum-1]+1; r[sum]=sum*sz;
23         minv[sum]=INF;
24         for(int i=l[sum];i<=r[sum];i++) {if(minv[sum]>a[i])minv[sum]=a[i]; num[i]=sum;}
25       }
26     l[sum]=r[sum-1]+1; r[sum]=n;
27     minv[sum]=INF;
28     for(int i=l[sum];i<=r[sum];i++) {if(minv[sum]>a[i])minv[sum]=a[i]; num[i]=sum;}
29 }
30 inline void work(const int &L,const int &R)
31 {
32     int *t=&(minv[num[L]]);
33     *t=INF;
34     int *z;
35     for(int i=L,*z=a+i;i<=R;i++,z++) {*z-=v;if(*t>*z)*t=*z;}
36     for(int i=r[num[L]],*z=a+i;i>R;i--,z--) if(*t>*z)*t=*z;
37     for(int i=l[num[L]],*z=a+i;i<L;i++,z++) if(*t>*z)*t=*z;
38 }
39 inline int update()
40 {
41     if(num[x]==num[y]) {work(x,y);return minv[num[x]]+delta[num[x]];}
42         work(x,r[num[x]]); work(l[num[y]],y);
43         int z;
44         if(minv[num[x]]+delta[num[x]]>minv[num[y]]+delta[num[y]])
45             z=minv[num[y]]+delta[num[y]];
46         else
47             z=minv[num[x]]+delta[num[x]];
48         for(int i=num[x]+1;i<num[y];i++) {delta[i]-=v;if(z>minv[i]+delta[i])z=minv[i]+delta[i];}
49       return z;
50 }
51 int main()
52 {
53     n=G(); m=G();
54     for(int i=1;i<=n;i++) a[i]=G();
55     makeblock();
56     for(int i=1;i<=m;i++)
57       {
58         v=G(); x=G(); y=G();
59         int z=update();
60         if(z<0)
61           {
62             printf("-1
%d
",i);
63             return 0;
64           }
65       }
66     puts("0");
67     return 0;
68 }
原文地址:https://www.cnblogs.com/autsky-jadek/p/4075340.html