湖南集训day7-LMLPHP

难度:☆☆☆☆☆☆

湖南集训day7-LMLPHP

湖南集训day7-LMLPHP

湖南集训day7-LMLPHP

/*
由观察可知 同种颜色的减去他的父亲值相同
我们考虑把询问的两个数分别减去小于它的最大斐波那契数。
*/
#include<iostream>
#include<cstdio>
#include<cstring> #define N 3000007
#define ll long long using namespace std;
ll n,m,x,y,ans,cnt1,cnt2;
ll feb[N]; inline ll read()
{
ll x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} inline ll swap(ll x, ll y)
{
ll tmp=x;x=y;y=tmp;
} int main()
{
freopen("fibonacci.in","r",stdin);
freopen("fibonacci.out","w",stdout);
feb[]=feb[]=;
for(int i=;i<=;i++) feb[i]=feb[i-]+feb[i-];
m=read();
while(m--)
{
x=read();y=read();
for(int i=;x!=y;i--)
{
if(x>feb[i]) x-=feb[i];
if(y>feb[i]) y-=feb[i];
}
printf("%lld\n",x);
}
fclose(stdin);fclose(stdout);
return ;
}

湖南集训day7-LMLPHP

湖南集训day7-LMLPHP

湖南集训day7-LMLPHP

/*
在vector里二分左右端点计算答案即可
也可以用动态开点线段树
分块和主席树写好看了应该也能搞过去
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm> #define N 300010 using namespace std;
vector<int>a[];
int pos[N];
int n,m,l,r,k,x; inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int main()
{
n=read();m=read();
for(int i=;i<=n;i++) pos[i]=read(),a[pos[i]].push_back(i);
for(int i=;i<=;i++)
sort(a[i].begin(),a[i].end());
for(int i=;i<=m;i++)
{
int opt;opt=read();
if(opt==)
{
l=read();r=read();k=read();
int ll=,rr=a[k].size()-,ans=-,mid;
while(ll<=rr)
{
mid=ll+rr>>;
if(a[k][mid]>=l) ans=mid,rr=mid-;
else ll=mid+;
}
if(ans==-){printf("0\n");continue;}
ll=,rr=a[k].size()-;int ans2=-;
while(ll<=rr)
{
int mid=ll+rr>>;
if(a[k][mid]<=r) ans2=mid,ll=mid+;
else rr=mid-;
}
if(ans2==-){printf("0\n");continue;}
else printf("%d\n",ans2-ans+);
}
else
{
x=read();
if(pos[x]==pos[x+]) continue;
else
{
a[pos[x]][lower_bound(a[pos[x]].begin(),a[pos[x]].end(),x)-a[pos[x]].begin()]++;
a[pos[x+]][lower_bound(a[pos[x+]].begin(),a[pos[x+]].end(),x+)-a[pos[x+]].begin()]--;
swap(pos[x],pos[x+]);
}
}
}
}

湖南集训day7-LMLPHP

湖南集训day7-LMLPHP

湖南集训day7-LMLPHP

/*
k==1 从后往前找最长的不冲突的,这样可以保证字典序最小
枚举k,k*k-a[i]==a[j]说明a[i]与a[j]的和是一个完全平方数。 k==2 部分分可以二分图染色
用并查集“敌人集合”维护冲突关系。
注意特判数相等的情况(k*k==a[j]*2)
*/
#include<iostream>
#include<cstdio>
#include<cstring> #define N 131073 using namespace std;
int n,m,K;
int a[N],b[N],f[N<<];
bool vis[N],dvis[N],issqr[N<<]; inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} int find(int x){
return f[x]>?(f[x]=find(f[x])):x;
} void merge(int u,int v)
{
u=find(u),v=find(v);
if(u!=v)
{
if(f[u]>f[v]) swap(u,v);
f[u]+=f[v];f[v]=u;
}
} bool check(int u,int v)
{
int r1=find(u),r2=find(u+N);
int s1=find(v),s2=find(v+N);
if(r1==s1 || r2==s2) return true;
merge(r1,s2);merge(r2,s1);
return false;
} void solve1()
{
for(int i=n,j=n;i;)
{
for(bool flag=;j;j--)
{
for(int k=;k*k-a[j]<N;k++)
{
if(k*k-a[j]<=) continue;
if(vis[k*k-a[j]])
{
flag=;break;
}
}
if(!flag) break;vis[a[j]]=;
}
if(!j) break;b[++m]=j;
for(;i>j;i--) vis[a[i]]=;
}
} void solve2()
{
memset(f,-,sizeof f);
for(int i=;i*i<*N ;i++) issqr[i*i]=;
for(int i=n,j=n;i;)
{
for(bool flag=;j;j--)
{
if (vis[a[j]])
{
if (issqr[a[j]+a[j]])
{
if (dvis[a[j]]) break;
for (int k=;k*k-a[j]<N;k++)
{
if (k*k-a[j]<=) continue;
if (vis[k*k-a[j]] &&k*k!=a[j]*)
{
flag=;break;
}
}
if (!flag)break; dvis[a[j]]=;
}
}
else
{
for(int k=;k*k-a[j]<N;k++)
{
if(k*k-a[j]<=) continue;
if(vis[k*k-a[j]])
{
if(check(k*k-a[j],a[j]))
{
flag=;break;
}
}
}
if(!flag) break;vis[a[j]]=;
}
}
if(!j) break;b[++m]=j;
for(;i>j;i--) f[a[i]]=f[a[i]+N]=-,vis[a[i]]=,dvis[a[i]]=;
}
} int main()
{
freopen("division.in", "r", stdin);
freopen("division.out", "w", stdout);
scanf("%d%d",&n,&K);
for (int i=;i<=n;i++)
scanf("%d",&a[i]);
if (K==) solve1();
else solve2();
printf("%d\n",m+);
for (int i=m;i;i--) printf("%d ",b[i]);
putchar('\n');
return ;
}
05-07 15:41