码迷,mamicode.com
首页 > 其他好文 > 详细

NOI2014 DAY2 题解

时间:2014-08-16 18:30:20      阅读:469      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   数据   for   

当天下午3点拿到jcvb现场发来的数据,本地自测100+100+30=230。

BUAA成绩60+60+30=150。sad story~

 

动物园 zoo

 

既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]。

 

偌大的提示:kmp! 思路很简单,求出next数组,你会发现这是一棵树,求出根(0)~i路径上<i/2的元素有多少个。

 

BIT nlogn? 多组数据会被卡。(ok多个log也能过的策爷!人家是策爷!)

 

我跟dzy说,类似单调栈..反正栈上搞搞就行。(考试时请改手工栈,笔者RE60)

 

bubuko.com,布布扣
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define mo 1000000007
 8 #define maxn 1100000 
 9 using namespace std;
10 int v[maxn],nxt[maxn],first[maxn];
11 char ch[maxn];int next[maxn];
12 int q,n,tot,ans;
13 int st[maxn],top,cnt;
14 
15 void addedge(int x,int y){
16     v[++tot]=y;nxt[tot]=first[x];first[x]=tot;
17 }
18 
19 void getnext(){
20     next[1]=0;
21     for(int i=2;i<=n;i++){
22         int j=next[i-1];
23         while(ch[j+1]!=ch[i]&&j>0) j=next[j];
24         if(ch[j+1]==ch[i]) next[i]=j+1;
25         else next[i]=0;
26     }
27 }
28 
29 void dfs(int u){
30     ans=1ll*ans*(cnt+1)%mo; int t;
31     for(int i=first[u];i;i=nxt[i]){
32         st[++top]=v[i]; t=cnt;
33         while(st[cnt+1]*2<=v[i]) cnt++;
34         dfs(v[i]);
35         --top; cnt=t;
36     }
37 } 
38 
39 int main(){
40     freopen("zoo.in","r",stdin);freopen("zoo.out","w",stdout);
41     scanf("%d",&q);
42     while(q--){
43         scanf("%s",ch+1); n=strlen(ch+1);
44         getnext();
45         for(int i=0;i<=n;i++) first[i]=0; tot=0;
46         for(int i=1;i<=n;i++) addedge(next[i],i);
47         ans=1,top=cnt=0;
48         dfs(0);
49         printf("%d\n",ans);
50     }
51     return 0;
52 }
zoo.cpp

 

 

随机数生成器 random

 

傻逼题。暴力是n^2你可能以为是n^3去写线段树n^2logn那就70分洗洗睡吧。

 

最多取的数是2n,修改是o(n),所以总的复杂度是o(n^2)。

 

若评测机不给力请不要两次取模。同步赛选手没有能A的。

 

bubuko.com,布布扣
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #define MAXL 25000010
 8 #define MAXN 10010
 9 using namespace std;
10 typedef long long LL;
11 typedef short int SI;
12 int t[MAXL]; SI x[MAXL],y[MAXL];
13 SI sl[MAXN],sr[MAXN];
14 int X,A,B,C,D;
15 int n,m,q,l;
16 LL x0,x1; 
17 
18 void swap(int&x,int&y){
19     x^=y,y^=x,x^=y;
20 }
21 
22 int main(){
23     freopen("random.in","r",stdin);freopen("random.out","w",stdout);
24     scanf("%d%d%d%d%d",&X,&A,&B,&C,&D);
25     scanf("%d%d%d",&n,&m,&q);
26     x0=X,l=n*m;
27     for(int i=1;i<=l;i++){
28         t[i]=i;
29         x1=(x0*x0*A+x0*B+C)%D;
30         if(x1%i+1!=i) swap(t[x1%i+1],t[i]);
31         x0=x1;
32     }
33     int u,v;
34     while(q--){
35         scanf("%d%d",&u,&v);
36         if(u!=v) swap(t[u],t[v]);
37     }
38     SI px=1,py=0;
39     for(int i=1;i<=l;i++){
40         py++;if(py>m) px++,py=1;
41         x[t[i]]=px,y[t[i]]=py;
42     }
43     for(int i=1;i<=n;i++) sl[i]=1,sr[i]=m;
44     int tot=n+m-1;
45     for(int i=1;i<=l;i++)
46         if(sl[x[i]]<=y[i]&&y[i]<=sr[x[i]]){
47             tot--;
48             if(tot) printf("%d ",i);
49             else{
50                 printf("%d\n",i);
51                 break;
52             }
53             for(int j=1;j<x[i];j++) sr[j]=min(y[i],sr[j]);
54             for(int j=x[i]+1;j<=n;j++) sl[j]=max(y[i],sl[j]);
55         }
56     return 0;
57 }
random.cpp

 

 

购票 ticket

 

毫无疑问是今年比赛最有价值的题。30分送分,DP方程很显然。

 

dp[i]=min{dp[j]+(dist[i]-dist[j])*p[i]+q[i]),j是i的祖先

 

令k<j<i,dp[j]<dp[k]当且仅当(dp[j]-dp[k])/(dist[j]-dist[k])<p[i],其中dist[]单调递增。

 

所以维护下凸壳优化DP。

 

 

笔者给出的是逗比做法,简洁易懂。

 

bubuko.com,布布扣

插入红色点,维护凸壳性质,会删去非最优的黄框中的点,他们一定是连续的,且接在最后的。

 

考虑是在树上,回溯时凸壳要退一步,删去红色点,接回黄框中的点。

 

似乎好像是split/merge操作,我就弄了棵splay来搞。

 

还有是距离限制。1..x都失效,我们需要得到x+1..father[i]的凸壳。

 

于是套棵线段树,能得到任意两点之间的凸壳。凸壳上二分斜率DP~

 

时间复杂度是nlog^2,空间是nlogn,不对也是nlog^2。

 

PS:线段树套splay确实是我最信不过的树套了,我的代码在链上的效率不高。有很优秀的算法请分享我。

bubuko.com,布布扣

bubuko.com,布布扣
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<algorithm>
  7 #define INF 9000000000000000000LL
  8 #define eps 1e-10
  9 #define MAXN 200010
 10 using namespace std;
 11 typedef long long LL;
 12 LL s[MAXN],p[MAXN],q[MAXN],l[MAXN],dist[MAXN],dp[MAXN];
 13 int father[MAXN],dep[MAXN],st[MAXN];
 14 int ch[MAXN*30][2],f[MAXN*30],pre[MAXN*30],suc[MAXN*30],b[MAXN*30],cnt;
 15 int lc[MAXN][30],rc[MAXN][30];
 16 int n,t,now,tmp,low,high,mid;
 17 
 18 struct edge{
 19     int v,next;
 20 }e[MAXN];
 21 int h[MAXN],tot=0;
 22 
 23 void addedge(int x,int y){
 24     ++tot;e[tot].v=y;e[tot].next=h[x];h[x]=tot;
 25 }
 26 
 27 double cross(double a,double b,double c,double d){
 28     return a*d-b*c;
 29 }
 30 
 31 void rotate(int x,int t){
 32     if(!x) return;
 33     int y=f[x];
 34     f[x]=f[y];if(f[y]) ch[f[y]][ch[f[y]][1]==y]=x;
 35     ch[y][t]=ch[x][!t];if(ch[x][!t]) f[ch[x][!t]]=y;
 36     f[ch[x][!t]=y]=x;
 37 }
 38 
 39 void splay(int x,int goal){
 40     if(!x) return;
 41     while(f[x]!=goal){
 42         if(f[f[x]]==goal)
 43             rotate(x,ch[f[x]][1]==x);
 44         else{
 45             int y=f[x],t=(ch[f[y]][1]==y);
 46             if(ch[y][t]==x) rotate(y,t),rotate(x,t);
 47             else rotate(x,!t),rotate(x,t);
 48         }
 49     }
 50 }
 51 
 52 int find(int x){
 53     int ret=0;
 54     while(x)
 55         if(pre[x]==0||(double)(dp[b[x]]-dp[b[pre[x]]])<(double)(dist[b[x]]-dist[b[pre[x]]])*p[now])
 56             ret=x,x=ch[x][1];
 57         else
 58             x=ch[x][0];
 59     return ret;
 60 }
 61 
 62 int maintain(int x){
 63     int ret=0;
 64     while(x)
 65         if(pre[x]==0||cross(dist[b[x]]-dist[b[pre[x]]],dp[b[x]]-dp[b[pre[x]]],dist[now]-dist[b[x]],dp[now]-dp[b[x]])>eps)
 66             ret=x,x=ch[x][1];
 67         else
 68             x=ch[x][0];
 69     return ret;
 70 }
 71 
 72 struct segment_tree_node{
 73     int l,r,no,rt;
 74 }a[MAXN*6];
 75 
 76 void Build(int k,int l,int r){
 77     a[k].l=l;a[k].r=r;a[k].no=a[k/2].no+1;
 78     if(l==r) return;int mid=(l+r)>>1;
 79     Build(k*2,l,mid);
 80     Build(k*2+1,mid+1,r);
 81 }
 82 
 83 void Insert(int k){
 84     b[++cnt]=now,tmp=lc[now][a[k].no]=maintain(a[k].rt);
 85     if(tmp){
 86         splay(a[k].rt=tmp,0);
 87         if(t!=0&&t!=2) splay(rc[now][a[k].no]=suc[tmp],tmp);
 88         ch[tmp][1]=suc[f[cnt]=pre[cnt]=tmp]=cnt;
 89     }
 90         else a[k].rt=cnt;
 91     if(t==0||a[k].l==a[k].r) return;
 92     if(dep[now]<=a[k*2].r) Insert(k*2);
 93     else Insert(k*2+1);
 94 }
 95 
 96 void Delete(int k){
 97     if(tmp=lc[now][a[k].no]) splay(a[k].rt=tmp,0),ch[tmp][1]=suc[tmp]=rc[now][a[k].no]; else a[k].rt=0;
 98     if(t==0||a[k].l==a[k].r) return;
 99     if(dep[now]<=a[k*2].r) Delete(k*2);
100     else Delete(k*2+1);
101 }
102 
103 LL Query(int k,int x,int y){
104     if(t==0||x<=a[k].l&&a[k].r<=y){
105         int j=b[find(a[k].rt)];
106         return dp[j]+(dist[now]-dist[j])*p[now]+q[now];
107     }
108     LL ret=INF;
109     if(x<=a[k*2].r) ret=min(Query(k*2,x,y),ret);
110     if(y>=a[k*2+1].l) ret=min(Query(k*2+1,x,y),ret);
111     return ret;    
112 }
113 
114 
115 void dfs(int u){
116     now=u,dep[u]=dep[father[u]]+1,dist[u]=dist[father[u]]+s[u];
117     low=1,high=dep[father[u]];
118     while(low<=high){
119         mid=(low+high)>>1;
120         if(dist[u]-dist[st[mid]]<=l[u]) high=mid-1;
121         else low=mid+1;
122     }
123     dp[u]=dep[father[u]]?Query(1,high+1,dep[father[u]]):0;
124     st[dep[u]]=u;Insert(1);
125     for(int i=h[u];i;i=e[i].next) dfs(e[i].v);
126     now=u;
127     if(t!=0&&t!=2) Delete(1);
128 }
129 
130 char buf[10000000],*pt = buf,*o = buf;
131 LL getint(){
132     LL x = 0;
133     while((*pt < 0 || *pt > 9))    pt ++;
134     x = *pt++ - 48;
135     while(*pt >= 0 && *pt <= 9)    x = x * 10 + *pt ++ - 48;
136     return x;
137 }
138 
139 int main(){
140     freopen("ticket.in","r",stdin);freopen("ticket.out","w",stdout);
141     fread(buf,1,10000000,stdin); 
142     //scanf("%d%d",&n,&t);
143     n=getint(),t=getint();
144     for(int i=2;i<=n;i++){
145         father[i]=getint(),s[i]=getint(),p[i]=getint(),q[i]=getint(),l[i]=getint();
146     //    scanf("%d%lld%lld%lld%lld",&father[i],&s[i],&p[i],&q[i],&l[i]);
147         addedge(father[i],i);
148     }
149     Build(1,1,n);
150     dfs(1);
151     for(int i=2;i<=n;i++) printf("%lld\n",dp[i]);
152     return 0;
153 } 
ticket.cpp

NOI2014 DAY2 题解,布布扣,bubuko.com

NOI2014 DAY2 题解

标签:style   blog   http   color   os   io   数据   for   

原文地址:http://www.cnblogs.com/fullpower/p/3916666.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!