20171006

    对于昨天的考试,可以说是把暴力分都拿到了

 T1 的搜索方式还是根据了这道题的性质,就是总的步数很少,然后再贪心的由小往大的更新,这样时间效率几乎就是O(N)的;想要做出来这道题,首先就是要分析出来

往回走的步数其实是非常少的,至于如何分析出来,就可以直接打一个暴力,用一些时间搞出一些大数据的答案,然后再结合一下倍增的性质,应该就可以分析出来,然后就是如何去搜索,再搜索的时候,往往是和贪心减枝有紧密联系的,对于这道题,就是用小的步数去尽可能的更新多的点,然后之后枚举的步数就只用关注未确定步数的点

 T2的话,是一个莫比乌斯反演,其实这道题的暴力的极限应该是40分,但是当时还是不太懂μ做容斥系数的原理,这个可以做到√N的时间效率得到答案;今天又好好学习了一下莫比乌斯反演,不是那么的懵逼了,再莫比乌斯反演中,分块的思想可以大幅的提升时间效率,还是要做些题熟悉熟悉,具体的公式就不推了

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace std;
 8 # define maxN 30000010
 9 # define mod 76543
10 typedef long long LL;
11 LL n,N;
12 int su[maxN],mu[maxN],tot;
13 bool nosu[maxN];
14 void Find_mu(){
15     N=maxN-10;
16     mu[1]=1;
17     for(int i=2;i<=N;i++){
18         if(!nosu[i]){
19             su[++tot]=i; mu[i]=-1;
20         }
21         for(int j=1;j<=tot;j++){
22             if((LL)i*su[j]>N) break;
23             nosu[i*su[j]]=1;
24             if(i%su[j]==0){mu[i*su[j]]=0; break;}
25             mu[i*su[j]]=-mu[i];
26         }
27     }
28     for(int i=1;i<=N;i++) mu[i]+=mu[i-1];
29 }
30 struct node{
31     LL v,w; int nxt;
32 }g[maxN/10];
33 int adj[80010],e;
34 void add(int u,LL v,LL w){
35     g[e].v=v; g[e].w=w; g[e].nxt=adj[u];
36     adj[u]=e++;
37 }
38 LL ps(LL x){
39     if(x<=N) return mu[x];
40     int k=x%mod;
41     for(int i=adj[k];i!=-1;i=g[i].nxt)
42         if(g[i].v==x) return g[i].w;
43     LL ans=1; LL nxt;
44     for(LL i=2;i<=x;i=nxt+1){
45         nxt=(x/(x/i));
46         ans-=(nxt-i+1)*ps(x/i);
47     }
48     add(k,x,ans);
49     return ans;
50 
51 }
52 LL find(LL i,LL j){
53     return ps(j)-ps(i-1);
54 }
55 int main(){
56     // freopen("123567_20.in","r",stdin);
57     // freopen("666.out","w",stdout);
58     scanf("%lld",&n);
59     Find_mu();
60     LL nxt; LL ans=0;
61     memset(adj,-1,sizeof(adj));
62     LL lim=sqrt(n);
63     // ot();
64     for(LL i=1;i<=lim;i=nxt+1){
65         nxt=sqrt(n/(n/(i*i)));
66         ans+=n/(i*i)*find(i,nxt); 
67     }
68     cout<<ans<<endl;
69 }
T2

T3直接用Treap模拟可以拿到60,现在平衡树发现自己只会无旋Treap了,有时间要把Splay看一看,然后正解是线段树,就是利用平衡树中的中序遍历就是原序列,可以直接把一个平衡树拍成一个序列,然后可以发现,对于某一个点,他的左边的以他自己为起点上升序列长度+右边以他自己为起点上升序列长度,就是他的深度,为什么的话,可以找到,再这个序列中,一个点的左子树和右子树分别在这个点的左右两边,又因为这是一个大根堆,那么反过来,这个点可能在他的祖先(不一定是父亲)的右子树或者左子树,所以他的每一个祖先可能不再同一侧,而一个祖先有一定比他的孩子的权值大(大根堆),所以上升序列的长度和就是深度; 然后就是怎么用线段树维护这个上升序列,这个线段树里的update是递归实现的,这个之前没有遇到过,其实就是讨论一个子树中左右区间的影响关系,然后递归实现就行了,要注意的是合并子树信息是的顺序;还有一点两个点的LCA就是在序列中两个点之间的最大值(可以用最基本的线段树查询实现);

  1 #pragma GCC optimize("O3")
  2 #include <cmath>
  3 #include <cstdio>
  4 #include <ctime>
  5 #include <cstring>
  6 #include <cstdlib>
  7 #include <iostream>
  8 #include <algorithm>
  9 # define maxn 200010
 10 using namespace std;
 11 void ot(){cout<<"******"<<endl;}
 12 struct QQ{
 13     int od,x,y;
 14 }q[maxn];
 15 typedef pair<int,int> D;
 16 D Max(D a,D b){return a.first>b.first? a:b;}
 17 int n,m,N;
 18 int hs[maxn];
 19 int ans1[4*maxn],ans2[4*maxn];
 20 D mx[4*maxn];
 21 bool cmp1(const int a,const int b){return a<b;}
 22 void lsan(){
 23     sort(hs+1,hs+N+1,cmp1);
 24     int cnt=unique(hs+1,hs+N+1)-hs-1;
 25     for(int i=1;i<=n;i++){
 26         if(q[i].od==2){
 27             q[i].x=lower_bound(hs+1,hs+cnt+1,q[i].x)-hs;
 28             q[i].y=lower_bound(hs+1,hs+cnt+1,q[i].y)-hs;
 29         }
 30         else q[i].x=lower_bound(hs+1,hs+cnt+1,q[i].x)-hs;
 31     }
 32     N=cnt;
 33 }
 34 void init(){
 35     scanf("%d",&n);
 36     for(int i=1;i<=n;i++){
 37         scanf("%d",&q[i].od);
 38         if(q[i].od==0){
 39             scanf("%d%d",&q[i].x,&q[i].y);
 40             hs[++N]=q[i].x;
 41         }
 42         if(q[i].od==1){
 43             scanf("%d",&q[i].x);
 44         }
 45         if(q[i].od==2){
 46             scanf("%d%d",&q[i].x,&q[i].y);
 47             if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
 48         }
 49     }
 50     lsan();
 51 }
 52 int cal1(int now,int l,int r,int h){
 53     if(l==r) return mx[now].first>h? 1:0;
 54     if(h>mx[now].first) return 0;
 55     int mid=(l+r)>>1;
 56     if(mx[now<<1].first<=h) return cal1(now<<1|1,mid+1,r,h);
 57     else return cal1(now<<1,l,mid,h)+ans1[now]-ans1[now<<1];
 58 }
 59 int cal2(int now,int l,int r,int h){
 60     if(l==r) return mx[now].first>h? 1:0;
 61     if(h>mx[now].first) return 0;
 62     int mid=(l+r)>>1;
 63     if(mx[now<<1|1].first<=h) return cal2(now<<1,l,mid,h);
 64     else return cal2(now<<1|1,mid+1,r,h)+ans2[now]-ans2[now<<1|1];
 65 }
 66 void change(int ch,int now,int l,int r,int num){
 67     if(l==r){
 68         ans1[now]=ans2[now]=1; mx[now]=D(num,l); return;
 69     }
 70     int mid=(l+r)>>1;
 71     if(ch<=mid) change(ch,now<<1,l,mid,num);
 72     if(ch>mid) change(ch,now<<1|1,mid+1,r,num);
 73     mx[now]=max(mx[now<<1],mx[now<<1|1]);
 74     ans1[now]=ans1[now<<1]+cal1(now<<1|1,mid+1,r,mx[now<<1].first);
 75     ans2[now]=ans2[now<<1|1]+cal2(now<<1,l,mid,mx[now<<1|1].first);
 76 }
 77 D query3(int left,int right,int now,int l,int r){
 78     if(left<=l && r<=right) return mx[now];
 79     int mid=(l+r)>>1;
 80     D ret;
 81     if(left<=mid) ret=max(ret,query3(left,right,now<<1,l,mid));
 82     if(right>mid) ret=max(ret,query3(left,right,now<<1|1,mid+1,r));
 83     return ret;
 84 }
 85 struct RRR{
 86     int ans,rt,l,r,mx;
 87     RRR(int a = 0,int b = 0,int c = 0,int d = 0,int e = 0){
 88         ans=a; rt=b; l=c; r=d; mx=e;
 89     }
 90 };
 91 RRR Mer1(RRR a,RRR b){
 92     if(a.ans==-1) return b;
 93     if(b.ans==-1) return a;
 94     RRR ret; 
 95     ret.mx=max(a.mx,b.mx);
 96     ret.ans=a.ans+cal1(b.rt,b.l,b.r,a.mx);
 97     return ret;
 98 }
 99 RRR query1(int left,int right,int now,int l,int r){
100     if( left<=l && r<=right){ 
101         return RRR(ans1[now],now,l,r,mx[now].first);
102     }
103     int mid=(l+r)>>1;
104     RRR a,b,ret; a.ans=-1,b.ans=-1;
105     if(left<=mid) a=query1(left,right,now<<1,l,mid);
106     if(right>mid) b=query1(left,right,now<<1|1,mid+1,r);
107     ret=Mer1(a,b);
108     return ret;
109 }
110 RRR Mer2(RRR a,RRR b){
111     if(a.ans==-1) return b;
112     if(b.ans==-1) return a;
113     RRR ret;
114     ret.mx=max(a.mx,b.mx);
115     ret.ans=b.ans+cal2(a.rt,a.l,a.r,b.mx);
116     return ret;
117 }
118 RRR query2(int left,int right,int now,int l,int r){
119     if(left<=l && r<=right){ return RRR(ans2[now],now,l,r,mx[now].first);}
120     int mid=(l+r)>>1;
121     RRR a,b,ret; a.ans=-1,b.ans=-1;
122     if(right>mid) b=query2(left,right,now<<1|1,mid+1,r);
123     if(left<=mid) a=query2(left,right,now<<1,l,mid);
124     return Mer2(a,b);
125     return ret;
126 }
127 void work(){
128     for(int i=1;i<=n;i++){
129         if(q[i].od==0){
130             change(q[i].x,1,1,N,q[i].y);
131             // cout<<q[i].x<<endl;
132         }
133         if(q[i].od==1){
134             change(q[i].x,1,1,N,0);
135         }
136         if(q[i].od==2){
137             // printf("pos== %d %d
",q[i].x,q[i].y );
138             int dx=query1(q[i].x,N,1,1,N).ans+query2(1,q[i].x,1,1,N).ans;  //query1(q[i].x,N,1,1,N).ans+
139             int dy=query1(q[i].y,N,1,1,N).ans+query2(1,q[i].y,1,1,N).ans;
140             int k=query3(q[i].x,q[i].y,1,1,N).second;
141             int dl=query1(k,N,1,1,N).ans+query2(1,k,1,1,N).ans;
142             // printf("ans== %d %d
",ans1[1],ans2[1]);
143             // printf("k= %d
",k);
144             // printf("dep== %d %d %d
",dx,dy,dl);
145             printf("%d
",dx+dy-2*dl);
146         }
147         // if(i==5) exit(0);
148     }
149 }
150 int main(){
151     // freopen("treap_1.in","r",stdin);
152     // freopen("666.out","w",stdout);
153     init();
154     work();
155 }
View Code
原文地址:https://www.cnblogs.com/FOXYY/p/7634406.html