bzoj 3535Fair Photography【hash】

来源:互联网 发布:ubuntu 安装区间 编辑:程序博客网 时间:2024/06/10 06:19

很容易想到枚举出现的位置,哈希一个前缀和,判定有无出现过。

这样复杂度有点大。

hzwer给出了一个小的常数优化:维护每个数和第一个出现的数的差值,这样只有改首个复杂度是k^2否则都是O(k)

注意细节

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define ull unsigned long long#define inf 1e9#define eps 1e-10#define md#define N 100010#define H 1000000#define B 10using namespace std;struct yts { ull a; int id,ne;};int mx,n,ans,K;int sum[B];int ne[N];bool mark[B];struct AA { int x,b;} a[N];const ull cheng1=23333333,cheng2=654321; struct hash{yts e[N];int v[H],q[N];int cnt;void clear(){for (int i=1;i<=cnt;i++) v[q[i]]=0;cnt=0;}int find(ull a,int id){int x=a%H,i;for (i=v[x];i;i=e[i].ne){if (e[i].a==a) break;}if (i) return e[i].id;i=++cnt; e[i].a=a; e[i].id=id;e[i].ne=v[x]; v[x]=i;q[i]=x;return -1;}} hash;bool cmp(AA a,AA b) { return a.x<b.x;}ull get(){ull ans=0;for (int i=0;i<=mx;i++) ans=ans*cheng1+((ull)(sum[i]+n))*cheng2;return ans;}void solve(){//for (int i=0;i<=mx;i++) printf("%d ",mark[i]); printf("\n");hash.clear(); memset(sum,0,sizeof(sum));hash.find(0,0);int fr=0; while (!mark[fr]) fr++;for (int i=1;i<=n;i++){if (!mark[a[i].b]) {hash.clear(); hash.find(0,i);memset(sum,0,sizeof(sum));//printf("__ %d %d\n",a[i].x,a[i].b);}else{if (a[i].b==fr){for (int j=fr+1;j<=mx;j++)  if (mark[j]) sum[j]--;}else sum[a[i].b]++;//printf("%d %d : ",a[i].x,a[i].b); for (int j=0;j<=mx;j++) printf("%d ",sum[j]);ull dt=get(); //printf("%llu\n",dt);int pre=hash.find(dt,i);if (pre!=-1) ans=max(ans,a[i].x-ne[pre]);}}}void dfs(int dep,int k){if (dep>mx){if (k>=K) solve();return;}dfs(dep+1,k);mark[dep]=1;dfs(dep+1,k+1);mark[dep]=0;}int main(){#ifndef ONLINE_JUDGEfreopen("data.in","r",stdin); freopen("data.out","w",stdout);#endifscanf("%d%d",&n,&K);for (int i=1;i<=n;i++){scanf("%d%d",&a[i].x,&a[i].b);a[i].b--; mx=max(mx,a[i].b);}sort(a+1,a+n+1,cmp);for (int i=1;i<=n;i++) ne[i-1]=a[i].x;dfs(0,0);if (ans) printf("%d\n",ans);else printf("-1\n");return 0;}


0 0
原创粉丝点击