【NOIP模擬】斐波那契+序列+柵欄
阿新 • • 發佈:2018-12-14
T1:
Hash
程式碼(map實現):
#include <bits/stdc++.h> #include <tr1/unordered_map> using namespace std; using namespace std::tr1; const int Max=100010; int n,m,tot,ans=1; int fib[50],p[Max]; unordered_map<long long,bool>vis; inline int get_int() { int x=0,f=1; char c; for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar()); if(c=='-') f=-1,c=getchar(); for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0'; return x*f; } int main() { fib[1]=1; for(int i=2;i<=42;i++) fib[i]=fib[i-1]+fib[i-2]; n=get_int(),p[++tot]=get_int(),vis[p[1]]=1; for(int i=2;i<=n;i++) { int x=get_int(),tag=0; for(int j=42;j>=1;j--) { if(fib[j]-x<=0) break; if(vis[fib[j]-x]){tag=1;break;} } if(tag) p[tot=1]=x,ans++,vis.clear(),vis[x]=1; else p[++tot]=x,vis[x]=1; } cout<<ans; return 0; }
T2:
主席樹。
程式碼(30分平衡樹):
#include <bits/stdc++.h> #define int long long using namespace std; const int Max=100005; int n,m,tot,root,s,pos; int num[Max],f[1005][1005]; struct shu{int l,r,data,num,size,cnt;}; shu a[1005]; inline int get_int() { int x=0,f=1; char c; for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar()); if(c=='-') f=-1,c=getchar(); for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0'; return x*f; } inline void print(int x) { if(x<0) x=-x,putchar('-'); if(x>9) print(x/10); putchar('0'+x%10); } inline void update(int p){a[p].size=a[a[p].l].size+a[a[p].r].size+a[p].cnt;} inline int NEW(int x) { a[++tot].num=x,a[tot].data=rand(); a[tot].size=a[tot].cnt=1; return tot; } inline void zig(int &p) { int q=a[p].l; a[p].l=a[q].r,a[q].r=p,p=q; update(a[p].r),update(p); } inline void zag(int &p) { int q=a[p].r; a[p].r=a[q].l,a[q].l=p,p=q; update(a[p].l),update(p); } inline void Insert(int &p,int x) { if(!p){p=NEW(x);return;} if(a[p].num==x) {a[p].cnt++,update(p);return;} if(x<a[p].num) { Insert(a[p].l,x); if(a[a[p].l].data>a[p].data) zig(p); } else { Insert(a[p].r,x); if(a[a[p].r].data>a[p].data) zag(p); } update(p); } inline int find(int p,int x) { if(a[a[p].l].size>=x) return find(a[p].l,x); if(a[a[p].l].size+a[p].cnt>=x) return a[p].num; return find(a[p].r,x-a[a[p].l].size-a[p].cnt); } inline void pre() { for(int i=1;i<=n;i++) { memset(a,0,sizeof(a)),root=s=tot=0; for(int j=i;j>=1;j--) { Insert(root,num[j]),s++; pos=(s%2)?s/2+1:s/2; f[i][i-j+1]=find(root,pos); } } } signed main() { n=get_int(); for(int i=1;i<=n;i++) num[i]=get_int(); pre(); m=get_int(); for(int i=1;i<=m;i++) { int l1=get_int(),r1=get_int(),l2=get_int(),r2=get_int(),ans=0; for(int i=l2;i<=n;i++) for(int j=l2;j<=r2;j++) if(f[i][j]>=l1&&f[i][j]<=r1) ans++; print(ans),putchar('\n'); } return 0; }
程式碼(100分主席樹):
#include <bits/stdc++.h> using namespace std; const int Max=100005; int n,m,tot; int root[Max*20],num[Max],lc[Max*20],rc[Max*20]; long long tree[Max*20],ans; inline int get_int() { int x=0,f=1; char c; for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar()); if(c=='-') f=-1,c=getchar(); for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0'; return x*f; } inline void print(long long x) { if(x<0) x=-x,putchar('-'); if(x>9) print(x/10); putchar('0'+x%10); } inline void add(int fa,int &now,int l,int r,int x) { now=++tot,tree[now]=tree[fa]+1,lc[now]=lc[fa],rc[now]=rc[fa]; if(l==r) return; int mid=(l+r)>>1; if(x<=mid) add(lc[fa],lc[now],l,mid,x); else add(rc[fa],rc[now],mid+1,r,x); } inline long long Q(int root1,int root2,int l,int r,int x) { if(x>=r) return tree[root1]-tree[root2]; int mid=(l+r)>>1; if(x<=mid) return Q(lc[root1],lc[root2],l,mid,x); return Q(lc[root1],lc[root2],l,mid,x)+Q(rc[root1],rc[root2],mid+1,r,x); } inline long long solve(int x,int l,int r) { int d=0; ans=0,tot=0,memset(tree,0,sizeof(tree)),memset(root,0,sizeof(root)); memset(lc,0,sizeof(lc)),memset(rc,0,sizeof(rc)); add(root[1],root[1],0,2*n,n); for(int i=1;i<=n;i++) { d+=((num[i]<=x)?1:-1); add(root[i],root[i+1],0,2*n,n+d); ans+=Q(root[max(i-l+1,0)],root[max(i-r,0)],0,2*n,d+n); } return ans; } int main() { n=get_int(); for(int i=1;i<=n;i++) num[i]=get_int(); m=get_int(); while(m--) { int x1=get_int(),y1=get_int(),x2=get_int(),y2=get_int(); print(solve(y1,x2,y2)-solve(x1-1,x2,y2)),putchar('\n'); } return 0; }
T3:
隨機化+二維樹狀陣列
程式碼(請忽略define部分。。。):
#define dzyo_ak_uoi long long
#include <bits/stdc++.h>
using namespace std;
const int Max=2010;
int n,m,q;
dzyo_ak_uoi sum[Max][Max];
map<pair<pair<int,int>,pair<int,int> >,int>S;
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') f=-1,c=getchar();
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void print(int x)
{
if(x<0) x=-x,putchar('-');
if(x>9) print(x/10);
putchar('0'+x%10);
}
inline void add(int x,int y,dzyo_ak_uoi num)
{
for(int i=x;i<=n;i+=i&(-i))
for(int j=y;j<=m;j+=j&(-j))
sum[i][j]^=num;
}
inline dzyo_ak_uoi Q(int x,int y)
{
dzyo_ak_uoi ans=0;
for(int i=x;i;i-=i&(-i))
for(int j=y;j;j-=j&(-j))
ans^=sum[i][j];
return ans;
}
int main()
{
srand(time(0));
n=get_int(),m=get_int(),q=get_int();
while(q--)
{
int tag=get_int(),x1=get_int(),y1=get_int(),x2=get_int(),y2=get_int();
if(tag==1)
{
dzyo_ak_uoi num=rand()*65536+rand();
add(x1,y1,num),add(x2+1,y1,num),add(x1,y2+1,num),add(x2+1,y2+1,num);
S[make_pair(make_pair(x1,y1),make_pair(x2,y2))]=num;
}
if(tag==2)
{
dzyo_ak_uoi ad=S[make_pair(make_pair(x1,y1),make_pair(x2,y2))];
add(x1,y1,ad),add(x2+1,y1,ad),add(x1,y2+1,ad),add(x2+1,y2+1,ad);
}
if(tag==3) (Q(x1,y1)==Q(x2,y2))?cout<<"Yes\n":cout<<"No\n";
}
return 0;
}