雅礼集训 2017 Day1

T1:loj 6029 市场

题目大意:

维护一个数据结构支持区间加 区间除法 区间求最小值 区间求和

思路:

用线段树维护区间加 区间求最小值 区间和

对于区间除法 注意到除数d很大而加法的w很小

尝试将区间除法变成区间减法

可以转化成减法的情况就是除法的时候减的数相同即区间内所有数相同或最小数和最大数相差为一且最大数为除数的倍数

即维护区间min max 加减法tag sum即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<map>
 9 #define ll long long
10 #define inf 2147483611
11 #define MAXN 100100
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int n,q,g[MAXN];
21 ll sum[MAXN<<2],mn[MAXN<<2],tag[MAXN<<2],mx[MAXN<<2];
22 void upd(int k) {sum[k]=sum[k<<1]+sum[k<<1|1],mn[k]=min(mn[k<<1],mn[k<<1|1]),mx[k]=max(mx[k<<1],mx[k<<1|1]);}
23 void build(int k,int l,int r)
24 {
25     if(l==r) {sum[k]=mn[k]=mx[k]=g[l];return ;}
26     tag[k]=0;
27     int mid=(l+r)>>1;
28     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
29     upd(k);
30 }
31 void pshd(int k,int l,int r)
32 {
33     int mid=(l+r)>>1;
34     tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k];
35     mn[k<<1]+=tag[k],mn[k<<1|1]+=tag[k];
36     mx[k<<1]+=tag[k],mx[k<<1|1]+=tag[k];
37     sum[k<<1]+=(mid-l+1)*tag[k],sum[k<<1|1]+=(r-mid)*tag[k];
38     tag[k]=0;
39 }
40 void mdfp(int k,int l,int r,int a,int b,int x)
41 {
42     if(a==l&&r==b) {sum[k]+=(r-l+1)*x,tag[k]+=x,mn[k]+=x,mx[k]+=x;return ;}
43     int mid=(l+r)>>1;
44     if(tag[k]!=0) pshd(k,l,r);
45     if(b<=mid) mdfp(k<<1,l,mid,a,b,x);
46     else if(a>mid) mdfp(k<<1|1,mid+1,r,a,b,x);
47     else {mdfp(k<<1,l,mid,a,mid,x);mdfp(k<<1|1,mid+1,r,mid+1,b,x);}
48     upd(k);
49 } 
50 void mdfd(int k,int l,int r,int a,int b,int x)
51 {
52     if(l==a&&r==b&&mn[k]-(ll)floor(1.0*mn[k]/x)==mx[k]-(ll)floor(1.0*mx[k]/x))
53     {
54         ll tmp=mn[k]-(ll)floor(1.0*mn[k]/x);
55         sum[k]-=tmp*(r-l+1),mn[k]-=tmp,mx[k]-=tmp,tag[k]-=tmp;
56         return ;
57     }
58     int mid=(l+r)>>1;
59     if(tag[k]!=0) pshd(k,l,r);
60     if(b<=mid) mdfd(k<<1,l,mid,a,b,x);
61     else if(a>mid) mdfd(k<<1|1,mid+1,r,a,b,x);
62     else {mdfd(k<<1,l,mid,a,mid,x);mdfd(k<<1|1,mid+1,r,mid+1,b,x);}
63     upd(k);
64 }
65 ll querys(int k,int l,int r,int a,int b)
66 {
67     if(a==l&&r==b) return sum[k];
68     int mid=(l+r)>>1;
69     if(tag[k]!=0) pshd(k,l,r);
70     if(b<=mid) return querys(k<<1,l,mid,a,b);
71     else if(a>mid) return querys(k<<1|1,mid+1,r,a,b);
72     else return querys(k<<1,l,mid,a,mid)+querys(k<<1|1,mid+1,r,mid+1,b);
73 }
74 ll querym(int k,int l,int r,int a,int b)
75 {
76     if(a==l&&r==b) return mn[k];
77     int mid=(l+r)>>1;
78     if(tag[k]!=0) pshd(k,l,r);
79     if(b<=mid) return querym(k<<1,l,mid,a,b);
80     else if(a>mid) return querym(k<<1|1,mid+1,r,a,b);
81     else return min(querym(k<<1,l,mid,a,mid),querym(k<<1|1,mid+1,r,mid+1,b));
82 }
83 int main()
84 {
85     n=read(),q=read();int a,b,c;
86     for(int i=1;i<=n;i++) g[i]=read();
87     build(1,1,n);
88     while(q--)
89     {
90         a=read();
91         if(a==1) {a=read(),b=read(),c=read();mdfp(1,1,n,a+1,b+1,c);}
92         else if(a==2) {a=read(),b=read(),c=read();mdfd(1,1,n,a+1,b+1,c);}
93         else if(a==3) {a=read(),b=read();printf("%lld
",querym(1,1,n,a+1,b+1));}
94         else if(a==4) {a=read(),b=read();printf("%lld
",querys(1,1,n,a+1,b+1));}
95     }
96 }
View Code

T2:loj 6030 矩阵

题目大意:

一个黑白矩阵 可以把一行的顺序变成一列

求最少操作数

思路:

可以先做出一行黑色的

然后把所有不是完整一列的黑色变成黑色

做出黑色的最少步数是每一行的白色个数+(如果该行对应的列是否有黑色+1)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<map>
 9 #define ll long long
10 #define inf 2147483611
11 #define MAXN 1010
12 using namespace std;
13 inline int read()
14 {
15     int x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 int ok,n,f[MAXN],cnt1[MAXN],cnt2[MAXN],ans;
21 char maze[MAXN][MAXN];
22 int main()
23 {
24     n=read(),ans=2*n+1;
25     for(int i=1;i<=n;i++)
26     {
27         scanf("%s",maze[i]+1);
28         for(int j=1;j<=n;j++)
29             if(maze[i][j]=='#') f[j]=1,ok++;
30             else cnt1[i]++,cnt2[j]++;
31     }    
32     if(!ok) {puts("-1");return 0;}
33     for(int i=1;i<=n;i++)
34         ans=min(ans,cnt1[i]+(!f[i]?1:0));
35     for(int i=1;i<=n;i++)
36         ans+= cnt2[i]?1:0;
37     printf("%d",ans);
38 }
View Code

T3:loj 6031 字符串

原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9142216.html