@suixinhita
2017-10-24T09:41:43.000000Z
字数 4915
阅读 1179
反正...一旦开始了挂挂挂系列,就一时半会停不下来吧...
没谁是傻的吧...所以我们很清楚要用循环节了。
找出循环节之后,我们就可以搞事情了。
我们首先明确地知道,中间的循环节里面,每一个循环节显然都是出一个数的。
然后我们把最前面和最后面的摘出来跑一下。
中间循环节直接补上就可以了。
//有的数据可以卡掉这个程序。
#include<map>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e5+5;
int a[N],A,B,C,D;
int q[N],dp[N],cnt;
ll n,ans,an[N];
map<int,int> M;
void solve()
{
int len=1,i=1;
ll p=min((ll)N-1,n);
for(i=1;i<=p;++i)
{
if(i!=1) a[i]=(A*a[i-1]*a[i-1]%D+B*a[i-1]+C)%D;
if(M[a[i]]!=0)
{
len=i-M[a[i]];break;
}
else M[a[i]]=i;
}
for(int j=i+1;j<=i+len-1;++j)
a[j]=(A*a[j-1]*a[j-1]%D+B*a[j-1]+C)%D;
ll k=n-(ll)i+1-(((n-(ll)i+1)/(ll)len))*(ll)len;
int cnt=i+len-1;
for(int j=1;j<=k;++j)
{
int f=i+j-1;
a[++cnt]=a[f];
}
for(int j=1;j<=cnt;++j)
{
dp[j]=1;
for(int k=1;k<j;++k)
if(a[k]<=a[j]) dp[j]=max(dp[j],dp[k]+1);
an[j]=max(an[j-1],(ll)dp[j]);
}
int maxx=0;
ans=(n-(ll)cnt)/(ll)len+(ll)dp[cnt];
if(p==n) ans=an[i];
printf("%lld\n",ans);
}
int main()
{
freopen("lis.in","r",stdin);
freopen("lis.out","w",stdout);
scanf("%lld",&n);
scanf("%d%d%d%d%d",&a[1],&A,&B,&C,&D);
solve();
return 0;
}
这道题是我这段时间最尴尬的题,毕竟考场就知道该怎么写,结果剩下10min没调出来,gg.
其实看看数据返回很容易猜到,直接对于最小的取模,算出每一个模数需要的最小的地方就可以了。
这个就是个最短路。
注意:对于 的情况,我们直接苟一波bfs
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+5;
const ll inf=0x3f3f3f3f;
struct data{
int c,u;
};
ll V[N],dis[55][N],dist[N*30];
bool ind[55][N];
int L,C,ret[N],m,n,Q;
void bfs()
{
memset(dist,0x7f,sizeof(dist));
queue<int> q;
dist[0]=0;
q.push(0);
while(!q.empty())
{
int u=q.front();q.pop();
if(dist[u]>=C) continue;
for(int i=1;i<=n;++i)
{
ll v=u+V[i];
if((dist[v]<dist[u]+1))
{
dist[v]=dist[u]+1;
q.push(v);
}
}
}
for(int i=1;i<=n;++i) if(dist[i]>C) dist[i]=inf;
}
void spfa()
{
queue<data> q;
memset(dis,0x7f,sizeof(dis));
dis[0][0]=0,ind[0][0]=1;
data k;k.u=0,k.c=0;
q.push(k);
while(!q.empty())
{
data x=q.front();q.pop();
int u=x.u,c=x.c;data f;f=x;
for(int i=1;i<=n;++i)
{
//printf("L %lld\n",L);
int v=(u+ret[i])%Q;
// printf("%lld %lld\n",V[i],L);
if(V[i]>=L) f.c=c+1;
/* if(u==6&&(i==2||i==3))
{
puts("GG"),printf("%lld %lld\n",v,f.c),printf("%lld L %lld\n",V[i],L);
}
printf("%lld %lld\n",V[i],L);
*/ if(f.c>C) continue;
if(dis[f.c][v]>dis[c][u]+V[i])
{
f.u=v;
dis[f.c][v]=dis[c][u]+V[i];
if(!ind[f.c][v]) q.push(f),ind[f.c][v]=1;
}
}
ind[c][u]=0;
}
for(int i=0;i<Q;++i)
for(int c=0;c<=C;++c)
dis[0][i]=min(dis[0][i],dis[c][i]);
}
bool query(ll w)
{
ll p=w%Q;
if(dis[0][p]>w) return 0;
return 1;
}
int main()
{
// freopen("1.txt","r",stdin);
// freopen("11.txt","w",stdout);
ll k;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%lld",&V[i]);
sort(V+1,V+1+n);
Q=V[1];
for(int i=1;i<=n;++i) ret[i]=V[i]%Q;
scanf("%d%d",&L,&C);
//printf("------------------------\n%lld\n",L);
if(V[1]>L) bfs();
else spfa();
for(int i=1;i<=m;++i)
{
scanf("%lld",&k);
if(query(k)) puts("Yes");
else puts("No");
}
return 0;
}
裸树剖,于是开心的没写对...
就是,一旦修改了一个节点,就可以直接修改一个子树和他上面的所有其他值(见图)
所以我就不多说了。
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e6+5;
struct data{
int to,next;
}e[N];
int head[N],gs;
void add(int fr,int to)
{
e[++gs].to=to,e[gs].next=head[fr],head[fr]=gs;
}
int num[N],n,m,v[N];
struct node{
int mx,tag;
};
class st
{
private:
node t[N<<3];
int a,b,delt;
void update(int x)
{
int ls=x<<1,rs=x<<1^1;
if(t[ls].mx<t[rs].mx) t[x].mx=t[rs].mx;
else t[x].mx=t[ls].mx;
}
void pushdown(int x)
{
int ls=x<<1,rs=x<<1^1;
if(t[ls].tag<t[x].tag) t[ls].tag=t[x].tag;
if(t[rs].tag<t[x].tag) t[rs].tag=t[x].tag;
if(t[ls].mx<t[ls].tag) t[ls].mx=t[ls].tag;
if(t[rs].mx<t[rs].tag) t[rs].mx=t[rs].tag;
// t[x].tag=t[x].tagp=0;
}
void change(int now,int l,int r)
{
pushdown(now);
if(a<=l&&r<=b)
{
t[now].mx=max(t[now].mx,delt);
t[now].tag=max(t[now].tag,delt);
return ;
}
int mid=l+r>>1;
if(a<=mid) change(now<<1,l,mid);
if(mid<b) change(now<<1^1,mid+1,r);
update(now);
}
int query(int now,int l,int r)
{
pushdown(now);
if(a<=l&&r<=b)
return t[now].mx;
int mid=l+r>>1;
int an=-1;
if(a<=mid) an=max(an,query(now<<1,l,mid));
if(mid<b) an=max(an,query(now<<1^1,mid+1,r));
return an;
}
public:
void CHANGE(int l,int r,int x)
{
a=l,b=r,delt=x;
change(1,1,n);
}
int QUERY(int l,int r)
{
a=l,b=r;
return query(1,1,n);
}
}T;
int size[N],fa[N],dep[N],son[N],top[N],pos[N],ed[N],cnt;
bool once[N],used[N];
void dfs1(int u)
{
size[u]=1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[u]) continue;
fa[v]=u,dep[v]=dep[u]+1;
dfs1(v);size[u]+=size[v];
if(size[v]>size[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;pos[u]=++cnt,num[cnt]=v[u];
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
ed[u]=cnt;
}
int query(int p)
{
return T.QUERY(pos[p],pos[p]);
}
void change(int x)
{
if(once[x]) return ;
once[x]=1;
T.CHANGE(pos[x],ed[x],v[x]);
while(x)
{
if(fa[x])
{
if(pos[fa[x]]<=pos[x]-1) T.CHANGE(pos[fa[x]],pos[x]-1,v[fa[x]]);
if(ed[fa[x]]>=ed[x]+1) T.CHANGE(ed[x]+1,ed[fa[x]],v[fa[x]]);
}
if(used[x]) break;
used[x]=1;
x=fa[x];
}
}
int main()
{
// freopen("lca.in","r",stdin);
// freopen("lca.out","w",stdout);
int x,y,k;
char s[10];
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&v[i]);
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs1(1);
dfs2(1,1);
for(int i=1;i<=m;++i)
{
scanf("%s%d",s+1,&x);
if(s[1]=='Q')
{
int ans=query(x);
printf("%d\n",ans==0?-1:ans);
}
else change(x);
}
return 0;
}