@suixinhita
2017-10-24T01:41:43.000000Z
字数 4915
阅读 1387
反正...一旦开始了挂挂挂系列,就一时半会停不下来吧...

没谁是傻的吧...所以我们很清楚要用循环节了。
找出循环节之后,我们就可以搞事情了。
我们首先明确地知道,中间的循环节里面,每一个循环节显然都是出一个数的。
然后我们把最前面和最后面的摘出来跑一下。
中间循环节直接补上就可以了。
//有的数据可以卡掉这个程序。#include<map>#include<cstdio>#include<algorithm>#define ll long longusing 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 longusing 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;}