1.支持以下操作:

A.对一个区间求最大值。

B.对一个区间的所有数&上一个数。

C.对一个区间的所有数|上一个数。

直接线段树维护。在修改的时候,如果继续修改没有意义,则打上标记。这也就意味着,我们需要维护当前区间上所有数字的某一个二进制位上的数是否相同,以及是多少。

打标记时,可以直接对另一个标记修改。

复杂度为nlog^2n,可以考虑势能分析。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=2E5+5;
  4 const int mask=(1<<21)-1;
  5 int n,m,a[maxn];
  6 int t[maxn*4],tagA[maxn*4],tagB[maxn*4];
  7 int what[maxn*4],can[maxn*4];
  8 bool leaf[maxn*4];
  9 inline int read()
 10 {
 11     char ch=getchar();
 12     while(!isdigit(ch))ch=getchar();
 13     int sum=ch-'0';ch=getchar();
 14     while(isdigit(ch)){sum=sum*10+ch-'0';ch=getchar();}
 15     return sum;
 16 }
 17 int G[55];
 18 inline void write(int x)
 19 {
 20     int g=0;
 21     do{G[++g]=x%10;x/=10;}while(x);
 22     for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
 23 }
 24 inline void pushup(int num)
 25 {
 26     if(leaf[num])
 27         return;
 28     int l=num<<1,r=num<<1|1;
 29     can[num]=(can[l]&can[r])&(mask^(what[l]^what[r]));
 30     what[num]=what[l];
 31     t[num]=max(t[l],t[r]);
 32 }
 33 void build(int l,int r,int num)
 34 {
 35     tagA[num]=mask;
 36     if(l==r)
 37     {
 38         t[num]=a[l];
 39         can[num]=mask;
 40         what[num]=t[num];
 41         leaf[num]=1;
 42         return;
 43     }
 44     int mid=(l+r)>>1;
 45     build(l,mid,num<<1),build(mid+1,r,num<<1|1);
 46     pushup(num);
 47 }
 48 inline void updateA(int num,int x)
 49 {
 50     what[num]&=(mask^can[num])|(can[num]&x);
 51 }
 52 inline void pushdownA(int num)
 53 {
 54     if(tagA[num]==mask)
 55         return;
 56     int x=tagA[num];
 57     tagA[num]=mask;
 58     t[num]&=x;
 59     updateA(num,x);
 60     if(leaf[num])
 61         return;
 62     tagA[num<<1]&=x;
 63     tagB[num<<1]&=x;
 64     t[num<<1]&=x;
 65     updateA(num<<1,x);
 66     tagA[num<<1|1]&=x;
 67     tagB[num<<1|1]&=x;
 68     t[num<<1|1]&=x;
 69     updateA(num<<1|1,x);
 70 }
 71 inline void updateB(int num,int x)
 72 {
 73     what[num]|=can[num]&x;
 74 }
 75 inline void pushdownB(int num)
 76 {
 77     if(tagB[num]==0)
 78         return;
 79     int x=tagB[num];
 80     tagB[num]=0;
 81     t[num]|=x;
 82     updateB(num,x);
 83     if(leaf[num])
 84         return;
 85     tagB[num<<1]|=x;
 86     tagA[num<<1]|=x;
 87     t[num<<1]|=x;
 88     updateB(num<<1,x);
 89     tagB[num<<1|1]|=x;
 90     tagA[num<<1|1]|=x;
 91     t[num<<1|1]|=x;
 92     updateB(num<<1|1,x);
 93 }
 94 inline void pushdown(int num)
 95 {
 96     pushdownB(num),pushdownA(num);
 97 }
 98 void changeA(int l,int r,int L,int R,int x,int num)
 99 {
100     pushdown(num);
101     if(L<=l&&r<=R)
102     {
103         int g=0;
104         bool flag=1;
105         g|=can[num]&x;
106         g|=mask^can[num];
107         if((mask^can[num])&(mask^x))
108             flag=0;
109         tagA[num]&=g;
110         if(l==r)
111         {
112             t[num]&=x;
113             pushdown(num);
114             can[num]=mask;
115             what[num]=t[num];
116             return;
117         }
118         if(flag)
119         {
120             pushdown(num);
121             pushup(num);
122             return;
123         }
124     }
125     pushdown(num);
126     int mid=(l+r)>>1;
127     if(R<=mid)
128         changeA(l,mid,L,R,x,num<<1);
129     else if(mid<L)
130         changeA(mid+1,r,L,R,x,num<<1|1);
131     else
132         changeA(l,mid,L,R,x,num<<1),changeA(mid+1,r,L,R,x,num<<1|1);
133     pushup(num);
134 }
135 void changeB(int l,int r,int L,int R,int x,int num)
136 {
137     pushdown(num);
138     if(L<=l&&r<=R)
139     {
140         tagB[num]|=can[num]&x;
141         x&=mask^can[num];
142         if(l==r)
143         {
144             t[num]|=x;
145             pushdown(num);
146             can[num]=mask;
147             what[num]=t[num];
148             return;
149         }
150     }
151     if(x==0)
152     {
153         pushdown(num);
154         pushup(num);
155         return;
156     }
157     pushdown(num);
158     int mid=(l+r)>>1;
159     if(R<=mid)
160         changeB(l,mid,L,R,x,num<<1);
161     else if(mid<L)
162         changeB(mid+1,r,L,R,x,num<<1|1);
163     else
164         changeB(l,mid,L,R,x,num<<1),changeB(mid+1,r,L,R,x,num<<1|1);
165     pushup(num);
166 }
167 int ask(int l,int r,int L,int R,int num)
168 {
169     pushdown(num);
170     if(L<=l&&r<=R)
171     {
172         pushup(num);
173         return t[num];
174     }
175     int mid=(l+r)>>1,ans=0;
176     if(R<=mid)
177         ans=ask(l,mid,L,R,num<<1);
178     else if(mid<L)
179         ans=ask(mid+1,r,L,R,num<<1|1);
180     else
181         ans=max(ask(l,mid,L,R,num<<1),ask(mid+1,r,L,R,num<<1|1));
182     pushup(num);
183     return ans;
184 }
185 int main()
186 {
187     freopen("a.in","r",stdin);
188     freopen("a.out","w",stdout);
189     ios::sync_with_stdio(false);
190     n=read(),m=read();
191     for(int i=1;i<=n;++i)
192         a[i]=read();
193     build(1,n,1);
194     while(m--)
195     {
196         int opt=read(),l=read(),r=read(),x;
197         if(l>r)
198             swap(l,r);
199         if(opt==3)
200             write(ask(1,n,l,r,1));
201         else
202         {
203             x=read();
204             if(opt==1)
205                 changeA(1,n,l,r,x,1);
206             else
207                 changeB(1,n,l,r,x,1);
208         }
209     }
210     return 0;
211 }
View Code

2.爱丽丝和鲍勃在树上进行博弈游戏。轮流操作,每次将一个点涂成自己所对应的颜色,不能不涂。最后,他们都希望自己的连通块数减去对方的连通块数最大,问最优策略是什么?

考虑涂完颜色后的数。不妨设爱丽丝的颜色为A,鲍勃的颜色为B。对于一个A节点,若有k个A节点相连,相当于连通块数少了k;若有k个B节点相连,如果把这个点涂成B,能够让对方减少k个连通块。也就是说,谁涂了度数越大的点,谁就更不利。

因此最优策略为将度数从小到大排序,依次选取(没有顺序之分)。


3.现实版方格数树!你站在原点处,在(0,n-1)*(n-1,0)的正方形中,每个整点上都有一颗半径为r的树。问你能看到多少树?(能看到当且仅当存在一条过原点的直线,与圆有交点,且与前面的其他圆没有任何交点)。n<=1E9,r的精确到小数点后6位。

对于(x,y),若x和y不互质,则一定看不到。

若(x,y)互质,能看到当且仅当$x^2+y^2<\frac{1}{r^2}$。

容斥即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<algorithm>
 8 #define N 1000000
 9 using namespace std;
10 typedef long long ll;
11 typedef long double ld;
12 ld M;
13 int n,r,mu[1000010],pri[1000010],tot,ans;
14 bool flag[1000010];
15 inline ll f(ld M,int n)
16 {
17   ll ans=0;
18   int t=(int)sqrt(M);
19   for(int B=1;B<=t && B<=n;B++)
20     ans+=min((ll)n,(ll)(ceil(sqrt(M-1ll*B*B))-1));
21   return ans;
22 }
23 int main()
24 {
25   freopen("b.in","r",stdin);
26   freopen("b.out","w",stdout);
27   cin>>n>>r;
28   M=1e12/r/r;
29   mu[1]=1;
30   n--;
31   for(int i=2;i<=N;i++)
32   {
33     if(flag[i]==0) pri[++tot]=i,mu[i]=-1;
34     for(int j=1;j<=tot && 1ll*i*pri[j]<=N;j++)
35     {
36       flag[i*pri[j]]=1;
37       if(i%pri[j]==0){mu[i*pri[j]]=0; break;}
38       else mu[i*pri[j]]=-mu[i];
39     }
40   }
41   ll ans=0;
42   for(int i=1;i<=N;i++)
43     if(mu[i]!=0) ans+=mu[i]*f(M/i/i,n/i);
44   cout<<ans+2<<endl;
45   return 0;
46 }
View Code

 

 posted on 2020-03-10 17:16  GreenDuck  阅读(119)  评论(0编辑  收藏  举报