【ContestHunter】【弱省胡策】【Round6】
KMP/DP+树链剖分+线段树/暴力
今天考的真是……大起大落……
String
QwQ题意理解又出错了……(还是说一开始理解了,后来自己又忘了为什么是这样了?)
反正最后的结果就是……我当成:后面每行只需要和第一行check一下就可以了。
因为那个图真的很像在搞串的匹配啊……一格一格往过移,看能不能匹配
然后不就是每个s[i]对A取一下模,然后KMP?看有多少个位置能匹配咯。。。
(其实这是A=B时的做法)
将原序列增长一倍(复制一遍),对A取模做一遍,然后再对B取模做一遍,看有哪些位置是合法的,统计一下……
然而其实正解可以证明出来当$A \not = B$的时候,可以当A=B做……也就是说,上面那种做法……是可以AC的-_-b
P.S.正解是KMP来找循环节= = n如果可以整除n-next[n],那么循环节长度就是n-next[n]……可匹配长度就是……那么多……啊反正差不多啦
1 //Round6 A 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define rep(i,n) for(int i=0;i<n;++i) 8 #define F(i,j,n) for(int i=j;i<=n;++i) 9 #define D(i,j,n) for(int i=j;i>=n;--i) 10 #define pb push_back 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=2000010; 20 /*******************template********************/ 21 22 23 int a[N],b[N],c[N],A,B,n,ans,nxt[N]; 24 bool yes[N]; 25 void init(){ 26 n=getint(); A=getint(); B=getint(); 27 F(i,1,n) a[i]=getint(); 28 memset(yes,0,sizeof yes); 29 ans=0; 30 } 31 void KMP(int *s,int n){ 32 int m=n*2; 33 nxt[1]=0; int j=0; 34 F(i,2,n+1){ 35 while(j && s[i]!=s[j+1]) j=nxt[j]; 36 if (s[i]==s[j+1]) j++; 37 nxt[i]=j; 38 } 39 j=0; 40 F(i,2,m-1){ 41 while(j && b[i]!=s[j+1]) j=nxt[j]; 42 if (b[i]==s[j+1]) j++; 43 if (j==n) yes[i]=1,j=nxt[j]; 44 } 45 } 46 void work(){ 47 F(i,1,n) c[i]=b[i]=b[i+n]=a[i]%A; 48 KMP(c,n); 49 if (A!=B){ 50 F(i,1,n) c[i]=b[i]=b[i+n]=a[i]%B; 51 KMP(c,n); 52 } 53 F(i,n,n*2-1) ans+=yes[i]; 54 printf("%d\n",ans?ans+1:0); 55 } 56 int main(){ 57 int T=getint(); 58 while(T--){ 59 init(); 60 work(); 61 } 62 return 0; 63 }
Tree
……30分的做法其实就是直接TreeDP,40~50的做法是线段树维护最大连续子段和,那么满分做法?两者结合……Orzzzzzz
所以就是树链剖分+DP(并没有?其实是贪心?)啊……
Orz zyf,这题代码感觉细节很多啊……
树链剖分一下,权值沿轻链按TreeDP的思路将权值加到fa上面,建出整个线段树……
然后每次修改的时候,先将这个点x到top[x]这一条重链上的ans更新一下(这里重点是maxl,即从左端点开始的最大连续子段和),然后!更新fa[top[x]]的DP值!因为它在线段树上的权值是自身权值+轻链的maxl,怎么搞?区间查询一下top[x]所在的重链的maxl……然后更新。。。【这里我并不知道如何记重链的结尾……因为dfs序记start和end是子树的,所以并不能那样搞。。。zyf的做法是:往出连轻链的时候多++一下dfs_clock,这样就可以将不同的重链断开,(当然是将这些没有编号的空节点的权值置为-INF)
查询的时候……直接出解呗。。。
1 //Round6 B 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<iostream> 6 #include<algorithm> 7 #define rep(i,n) for(int i=0;i<n;++i) 8 #define F(i,j,n) for(int i=j;i<=n;++i) 9 #define D(i,j,n) for(int i=j;i>=n;--i) 10 #define pb push_back 11 using namespace std; 12 typedef long long LL; 13 inline int getint(){ 14 int r=1,v=0; char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 16 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 17 return r*v; 18 } 19 const int N=500010,INF=1000000000; 20 /*******************template********************/ 21 22 int head[N],to[N],nxt[N],cnt; 23 void add(int x,int y){ 24 to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; 25 to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt; 26 } 27 28 int n,m,f[N],id[N],v[N],ans; 29 int pos[N],dfs_clock,fa[N],son[N],size[N],top[N]; 30 struct node{ 31 int max,maxl,maxr; 32 LL sum; 33 }t[N]; 34 bool vis[N]; 35 36 void dfs(int x){ 37 size[x]=1; son[x]=0; 38 int mx=0; 39 for(int i=head[x];i;i=nxt[i]) 40 if (to[i]!=fa[x]){ 41 fa[to[i]]=x; 42 dfs(to[i]); 43 size[x]+=size[to[i]]; 44 if (size[to[i]]>mx) son[x]=to[i],mx=size[to[i]]; 45 } 46 } 47 void connect(int x,int f){ 48 pos[x]=++m; top[x]=f; vis[x]=1; 49 id[m]=x; 50 if (son[x]) connect(son[x],f); 51 for(int i=head[x];i;i=nxt[i]) 52 if (!vis[to[i]]) 53 ++m,connect(to[i],to[i]); 54 } 55 56 #define L (o<<1) 57 #define R (o<<1|1) 58 #define mid (l+r>>1) 59 node maintain(node a,node b){ 60 node ans; 61 ans.maxl=max((LL)a.maxl,a.sum+b.maxl); 62 ans.maxr=max((LL)b.maxr,b.sum+a.maxr); 63 ans.max=max(a.maxr+b.maxl,max(a.max,b.max)); 64 ans.sum=a.sum+b.sum; 65 return ans; 66 } 67 void update(int o,int l,int r,int p,int v){ 68 if (l==r){ 69 t[o].sum+=v; 70 t[o].maxl=t[o].maxr=t[o].max=max(t[o].sum,(LL)0); 71 }else{ 72 if (p<=mid) update(L,l,mid,p,v); 73 else update(R,mid+1,r,p,v); 74 t[o]=maintain(t[L],t[R]); 75 } 76 } 77 node query(int o,int l,int r,int ql,int qr){ 78 if (l==ql && r==qr) return t[o]; 79 else if (qr<=mid) return query(L,l,mid,ql,qr); 80 else if (ql>mid) return query(R,mid+1,r,ql,qr); 81 else return maintain(query(L,l,mid,ql,mid),query(R,mid+1,r,mid+1,qr)); 82 } 83 void change(int x,int y1,int y2){ 84 while(x){ 85 int y=top[x],z=query(1,1,m,pos[y],m).maxl; 86 update(1,1,m,pos[x],y2-y1); 87 y1=z; y2=query(1,1,m,pos[y],m).maxl; 88 x=fa[top[x]]; 89 } 90 } 91 92 int main(){ 93 #ifndef ONLINE_JUDGE 94 freopen("sub.in","r",stdin); 95 freopen("sub.out","w",stdout); 96 #endif 97 n=getint(); int T=getint(); 98 F(i,1,n) v[i]=getint(); 99 F(i,2,n){ 100 int x=getint(),y=getint(); 101 add(x,y); 102 } 103 dfs(1); connect(1,1); 104 F(i,1,m) if (!id[i]) update(1,1,m,i,-INF); 105 F(i,1,n) change(i,0,v[i]); 106 while(T--){ 107 int cmd=getint(),x,y; 108 if (cmd==1){ 109 x=getint(), y=getint(); 110 change(x,v[x],y); 111 v[x]=y; 112 }else printf("%d\n",t[1].max); 113 } 114 return 0; 115 }
Transport
……我就无语了……
一开始我想的是二分!然后模拟过程进行判断!然而连样例都过不了……QwQ
仔细想了想好像确实并不满足单调性……会有小的波动……
然后蒟蒻就不会了……实在没办法了,二分的时候边界不是 $L=max\{a[i]\},R=\sum a[i]$ 嘛= =然后我就直接将二分的过程删掉……改成枚举……然后……TM居然就过了……maya我也是惊呆了,这个枚举的上下界明明很大的好吗……如果全都走一遍肯定要T的啊!然而我就是过了……就是这么神奇……>_>
P.S.这个边界 L 还是比较松的,其实应该弄成$max\{ \frac{\sum a[i]}{k}, max(a[i]) \}$ ?
1 //Round6 C 2 #include<cstdio> 3 #include<set> 4 #include<cstring> 5 #include<cstdlib> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 typedef long long LL; 14 inline int getint(){ 15 int r=1,v=0; char ch=getchar(); 16 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 17 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 18 return r*v; 19 } 20 const int N=100010; 21 /*******************template********************/ 22 23 int n,k,a[N],sum; 24 multiset<int>s,s2; 25 multiset<int>::iterator it; 26 bool check(int c){ 27 if (k*c<sum) return 0; 28 s2=s; 29 int num; 30 F(i,1,k){ 31 num=c; 32 do{ 33 if (s2.empty()) return 1; 34 it=s2.lower_bound(num); 35 if (it==s2.end()) it--; 36 if (*it>num){ 37 if (it==s2.begin()) break; 38 else it--; 39 } 40 num-=*it; 41 s2.erase(it); 42 }while(1); 43 } 44 return s2.empty(); 45 } 46 void init(){ 47 n=getint(); k=getint(); 48 s.clear(); 49 int L=0,R=0; 50 sum=0; 51 F(i,1,n){ 52 a[i]=getint(); 53 sum+=a[i]; R+=a[i]; L=max(L,a[i]); 54 s.insert(a[i]); 55 } 56 F(i,L,R) 57 if (check(i)){ 58 printf("%d\n",i); 59 return; 60 } 61 } 62 63 int main(){ 64 #ifndef ONLINE_JUDGE 65 freopen("C.in","r",stdin); 66 freopen("C.out","w",stdout); 67 #endif 68 int T=getint(); 69 while(T--) init(); 70 return 0; 71 }