10.6 考試
阿新 • • 發佈:2017-10-07
聯賽 ++ namespace .cn eap lld mes efi mic
T1
三個操作實際上是兩個
1.把x -1
2.把x *k
而100000的ans也不過是50步,因為是指數增長
設 f[i] 為走到i這個值用到的最少步數
那可以枚舉步數,然後來更新它能走到的位置
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cstdlib> #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long using namespaceT1std; const int N=1000006; int n; int f[N*10]; int main(){ scanf("%d",&n); mem(f,-1); f[1]=0; int step=0; while(f[n]==-1) { ++step; for(int i=0;i<=n+50;++i) if(f[i]!=-1) { if(f[i*(step-f[i])]==-1) f[i*(step-f[i])]=step; if(i>0) { if(f[i-1]==-1) f[i-1]=f[i]+1; else if(f[i-1]>f[i]+1) f[i-1]=f[i]+1; } } } cout<<f[n]; }
T2
不知道正解是什麽
他們從網上找了一篇17page的英文論文,我表示看不懂
然後 正哥打了杜教篩,O(n^(1/3)),正解好象是O(n^(0.4))...
ans=
x/(i*i)可以分塊,然後就轉化成了求mu的前綴和
要求前綴和範圍是1e9,但是只能預處理7e7...
所以要用杜教篩...(好,聯賽水題)
............(1)
這個就是莫比烏斯反演那個東西
只有當i==1的時候,才會==1
..........(2)
這個證明的話
(1)式,i=d*T,d是因數,T是倍數
(2)式,就變成 枚舉倍數,實際上是一樣的
然後(2)式 是遞歸形式,可以遞歸求,而且(2)式也可以分塊求
然後就可以在O(n^(1/3))計算出來了
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <cmath> #include <algorithm> #define ll long long #define dd double #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int N=70000006; const int mod=76543; int prime[2433706],cnt; bool he[N]; int mu[N]; void chu() { mu[1]=1; for(int i=2;i<N;++i) { if(!he[i]) { prime[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt&&(ll)prime[j]*i<N;++j) { he[i*prime[j]]=1; if(i%prime[j]==0) { mu[i*prime[j]]=0; break; } mu[i*prime[j]]=-mu[i]; } } for(int i=1;i<N;++i) mu[i]+=mu[i-1]; } ll n; struct son { ll u,v; int next; }a1[N/10]; int first[mod],e,ttt; inline void addbian(ll u,ll v) { ttt=u%mod; a1[e].v=v; a1[e].u=u; a1[e].next=first[ttt]; first[ttt]=e++; } ll presum(ll x) { if(x<N) return mu[x]; int kkk=x%mod; for(int i=first[kkk];i!=-1;i=a1[i].next) if(a1[i].u==x) return a1[i].v; ll nx,ans=1; for(ll i=2;i<=x;) { nx=x/(x/i); ans-=(nx-i+1)*presum(x/i); i=nx+1; } addbian(x,ans); return ans; } ll get(ll s,ll t) { return presum(t)-presum(s-1); } int main(){ mem(first,-1); chu(); scanf("%lld",&n); ll q1=sqrt((dd)n),nx,ans=0; for(ll i=1;i<=q1;) { nx=sqrt( n/(n/(i*i)) ); ans+=(n/(i*i))*get(i,nx); i=nx+1; } cout<<ans; }T2
T3
模擬Treap可以60分
正解是 線段樹
首先把詢問全都離線下來,離散一下
按照k為下標W為權值建線段樹
由於是大根堆,ku和kv的lca其實就是[ku,kv]區間w最大的那個值(這個其實可以想想Treap的建樹過程)
然後問題就只剩下 求ku,kv,lca到根節點的距離d了
d=pos向左向右的最長上升序列 (pos節點的父親節點的w一定比它大)
這個 最長上升序列長度 就可以用線段樹維護,這跟bzoj2957樓房重建一樣了
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cstdlib> #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long using namespace std; const int N=200006; struct Q { int op; ll t[2]; }q[N]; struct LI { int pos,ff; ll val; bool friend operator < (LI a,LI b) { return a.val<b.val; } }li[N*2]; int con; ll val[N*4]; int dui[N*4]; struct TREE { ll mx[N*8]; int cnt[N*8]; int cal(ll c,int l,int r,int x) { if(l==r) return mx[x]>c; int mid=(l+r)>>1; if(mx[x<<1]<=c) return cal(c,mid+1,r,x<<1|1); return cal(c,l,mid,x<<1)+cnt[x]-cnt[x<<1]; } inline void pushup(int l,int r,int x) { int mid=(l+r)>>1; mx[x]=(mx[x<<1]>mx[x<<1|1]?mx[x<<1]:mx[x<<1|1]); cnt[x]=cnt[x<<1]+cal(mx[x<<1],mid+1,r,x<<1|1); } void add(int pos,ll c,int l,int r,int x) { if(l==r) { mx[x]=c;cnt[x]=1; return ; } int mid=(l+r)>>1; if(pos<=mid) add(pos,c,l,mid,x<<1); else add(pos,c,mid+1,r,x<<1|1); pushup(l,r,x); } ll qqmax(int L,int R,int l,int r,int x) { if(L<=l&&r<=R) return mx[x]; int mid=(l+r)>>1; ll ans=0; if(L<=mid) ans=max(ans,qqmax(L,R,l,mid,x<<1)); if(mid<R) ans=max(ans,qqmax(L,R,mid+1,r,x<<1|1)); return ans; } int qq(int L,int R,int l,int r,int x) { //printf("Tsh L=%d R=%d l=%d r=%d x=%d\n",L,R,l,r,x); if(L<=l&&r<=R) return cnt[x]; int mid=(l+r)>>1,ans=0; if(R<=mid) return qq(L,R,l,mid,x<<1); if(mid<L) return qq(L,R,mid+1,r,x<<1|1); return qq(L,mid,l,mid,x<<1)+cal(qqmax(L,R,l,mid,x<<1),mid+1,r,x<<1|1); } }Tsh; struct TREe { ll mx[N*8]; int cnt[N*8]; int cal(ll c,int l,int r,int x) { if(l==r) return mx[x]>c; int mid=(l+r)>>1; if(mx[x<<1|1]<=c) return cal(c,l,mid,x<<1); return cal(c,mid+1,r,x<<1|1)+cnt[x]-cnt[x<<1|1]; } inline void pushup(int l,int r,int x) { int mid=(l+r)>>1; mx[x]=(mx[x<<1]>mx[x<<1|1]?mx[x<<1]:mx[x<<1|1]); cnt[x]=cnt[x<<1|1]+cal(mx[x<<1|1],l,mid,x<<1); } void add(int pos,ll c,int l,int r,int x) { if(l==r) { mx[x]=c;cnt[x]=1; return ; } int mid=(l+r)>>1; if(pos<=mid) add(pos,c,l,mid,x<<1); else add(pos,c,mid+1,r,x<<1|1); pushup(l,r,x); } ll qqmax(int L,int R,int l,int r,int x) { if(L<=l&&r<=R) return mx[x]; int mid=(l+r)>>1; ll ans=0; if(L<=mid) ans=max(ans,qqmax(L,R,l,mid,x<<1)); if(mid<R) ans=max(ans,qqmax(L,R,mid+1,r,x<<1|1)); return ans; } int qq(int L,int R,int l,int r,int x) { //printf("Txi L=%d R=%d l=%d r=%d x=%d\n",L,R,l,r,x); if(L<=l&&r<=R) return cnt[x]; int mid=(l+r)>>1,ans=0; if(R<=mid) return qq(L,R,l,mid,x<<1); if(mid<L) return qq(L,R,mid+1,r,x<<1|1); return qq(L,R,mid+1,r,x<<1|1)+cal(qqmax(L,R,mid+1,r,x<<1|1),l,mid,x<<1); } }Txi; int n,mm; int get(int pos) { //printf("pos=%d\n",pos); return Tsh.qq(pos,mm,1,mm,1)+Txi.qq(1,pos,1,mm,1); } void lisan() { for(int i=1;i<=n;++i) { if(q[i].op==0) li[++con]=(LI){i,0,q[i].t[0]}; else if(q[i].op==1) li[++con]=(LI){i,0,q[i].t[0]}; else { li[++con]=(LI){i,0,q[i].t[0]}; li[++con]=(LI){i,1,q[i].t[1]}; } } sort(li+1,li+1+con); li[0].val=-111;mm=0; for(int i=1;i<=con;++i) { if( li[i].val==li[i-1].val ) q[li[i].pos].t[li[i].ff]=mm; else q[li[i].pos].t[li[i].ff]=++mm; } con=0; for(int i=1;i<=n;++i) if(q[i].op==0) li[++con]=(LI){i,1,q[i].t[1]}; sort(li+1,li+1+con); for(int i=1;i<=con;++i) { q[li[i].pos].t[li[i].ff]=i; dui[i]=q[li[i].pos].t[0]; } } int main(){ //freopen("T3.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&q[i].op); if(q[i].op==0) scanf("%lld%lld",&q[i].t[0],&q[i].t[1]); else if(q[i].op==1) scanf("%lld",&q[i].t[0]); else scanf("%lld%lld",&q[i].t[0],&q[i].t[1]); } lisan(); /*printf("\n"); for(int i=1;i<=n;++i) printf("hhh %d %lld %lld\n",q[i].op,q[i].t[0],q[i].t[1]); printf("\n");*/ for(int i=1;i<=n;++i) { if(q[i].op==0) { Tsh.add(q[i].t[0],q[i].t[1],1,mm,1); Txi.add(q[i].t[0],q[i].t[1],1,mm,1); val[q[i].t[0]]=q[i].t[1]; } else if(q[i].op==1) { Tsh.add(q[i].t[0],-val[q[i].t[0]],1,mm,1); Txi.add(q[i].t[0],-val[q[i].t[0]],1,mm,1); } else { int lca; if(q[i].t[0]<=q[i].t[1]) lca=dui[Tsh.qqmax(q[i].t[0],q[i].t[1],1,mm,1)]; else lca=dui[Tsh.qqmax(q[i].t[1],q[i].t[0],1,mm,1)]; //printf("lca=%d\n",lca); printf("%d\n",get(q[i].t[0])+get(q[i].t[1])-2*get(lca) );//printf("i=%d\n",i); } } }T3
昨天這個題我感覺極其難,反正考試全都打了暴力...
但是 做難事必有所得 --------某建老師
做難題才有提升...
10.6 考試