A:整個串數字和%2==0,末尾%2==1,不就是挑出來兩個奇數嗎。。

1 #include<stdio.h> 2 #include<string.h> 3 #define it register int 4 #define ct const int 5 #define il inline 6 const int N=100005; 7 int T,n,s,o[N],cnt; 8 char a[N]; 9 int main(){ 10 scanf("%d",&T);it i; 11 while(T--){ 12 scanf("%d%s",&n,a+1),cnt=0; 13 for(i=1;cnt<2&&i<=n;++i) 14 if((a[i]-'0')&1) o[++cnt]=i; 15 if(cnt<2) puts("-1"); 16 else printf("%c%c\n",a[o[1]],a[o[2]]); 17 } 18 return 0; 19 }
B:由於只能變小不能變大,所以單升的必須滿足a[i]>=i-1,單降的滿足a[i]>=n-i。從前往后掃找到第一個不滿足a[i]>=i-1的,那么它的前面都是滿足單調升的。從后往前找第一個不滿足a[i]>=n-i的,那么它的后面都是滿足單調減的。如果有交集說明有解,否則無解。

1 #include<stdio.h> 2 #define it register int 3 #define ct const int 4 #define il inline 5 const int N=1000005; 6 int T,n,a[N]; 7 int main(){ 8 scanf("%d",&T);it i; 9 while(T--){ 10 scanf("%d",&n); 11 register bool fl=1;int pos1=0,pos2=0; 12 for(i=1;i<=n;++i){ 13 scanf("%d",&a[i]); 14 if(!pos1&&a[i]<i-1) pos1=i-1; 15 } 16 if(!pos1) pos1=n; 17 for(i=n;i;--i) if(a[i]<(n-i)){pos2=i+1;break;} 18 if(!pos2) pos2=1; 19 pos2>pos1?puts("No"):puts("Yes"); 20 } 21 return 0; 22 }
C:窩剛了一個半小時,真棒!一共試了三種算法,最后還是寫的暴力。。
枚舉一下現在強制多少人從左邊拿,遍歷剩下不聽他的人的人數,然后把從后往前和從前往后的最大值的最小值的最大值算出來就可以了。
upd:開始有一些用詞不當,經本校學弟@DFTMR指正已經修改。(窩好像次次C題的題解都能被揪出毛病來。。)

1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #define it register int 6 #define ct const int 7 #define il inline 8 using namespace std; 9 const int N=100005; 10 int ans,o,T,n,m,k,a[N]; 11 il int Min(ct p,ct q){return p<q?p:q;} 12 il int Max(ct p,ct q){return p>q?p:q;} 13 namespace io{ 14 il char nc(){ 15 static char buf[100000],*p1=buf,*p2=buf; 16 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 17 } 18 template <class I> 19 il void fr(I &num){ 20 num=0;register char c=nc();it p=1; 21 while(c<'0'||c>'9') c=='-'?p=-1,c=nc():c=nc(); 22 while(c>='0'&&c<='9') num=num*10+c-'0',c=nc(); 23 num*=p; 24 } 25 } 26 using io ::fr; 27 int main(){ 28 fr(T);it i,j; 29 while(T--){ 30 fr(n),fr(m),fr(k),ans=-2e9,k=Min(k,m-1);//最多控制前m-1個多了沒用 31 for(i=0;i<n;++i) fr(a[i]); 32 for(i=0;i<=k;ans=Max(ans,o),i++)//枚舉控制人數 33 for(j=0,o=2e9;j<m-k;j++) 34 o=Min(o,Max(a[i+j],a[n+i+j-m]));//n-(m-k-1-j)-(k-i)-1 就是算從前往后與從后往前的最大值的最小值 35 printf("%d\n",ans); 36 } 37 return 0; 38 }
D:一堆區間不強制在線顯然上莫隊。首先對於l==r的肯定是yes,然后對於有3種及以上字符的也是yes,如果首尾不同只要把尾放首首放尾肯定是yes,一種字符肯定是no。剩下兩種字符首尾相同的就是no了。真·結論題(雖然我ABD用的時間加一起還沒C多。。)

1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 #define it register int 6 #define ct const int 7 #define il inline 8 using namespace std; 9 const int N=1000005; 10 struct ky{ 11 int l,r,x,id; 12 }a[N]; 13 int n,m,bk,k,l,r,b[N],ans,s[N],o1[N]; 14 char S[N]; 15 bool cmp(ky a,ky b){ 16 return a.x^b.x?a.l<b.l:((a.x&1)?a.r<b.r:a.r>b.r); 17 } 18 int main(){ 19 scanf("%s",S+1),n=strlen(S+1); 20 for(it i=1;i<=n;++i) b[i]=S[i]-'a'+1; 21 it bk=sqrt(n),i; 22 scanf("%d",&m); 23 for(i=1;i<=m;i++) 24 scanf("%d%d",&a[i].l,&a[i].r),a[i].x=a[i].l/bk,a[i].id=i; 25 sort(a+1,a+1+m,cmp); 26 l=1,r=0; 27 for(i=1;i<=m;i++){ 28 if(a[i].l==a[i].r){o1[a[i].id]=1;continue;} 29 while(l<a[i].l) ans-=(!--s[b[l++]]); 30 while(l>a[i].l) ans+=(!s[b[--l]]++); 31 while(r<a[i].r) ans+=(!s[b[++r]]++); 32 while(r>a[i].r) ans-=(!--s[b[r--]]); 33 o1[a[i].id]=((ans==2&&b[a[i].l]!=b[a[i].r]||ans>2)?1:-1); 34 } 35 for(i=1;i<=m;i++) 36 o1[i]==-1?puts("No"):puts("Yes"); 37 return 0; 38 }
E:先鴿着
F:同E
先把cf官方題解搬來吧(雖然我覺得EF都挺可做的)
抱歉復制過來公式掛了將就着看吧。。
1290C - Prefix Enlightenment
The condition "the intersection of any three subsets is empty" can be easily rephrased in a more useful way: each element appears in at most two subsets.
Let's suppose for the moment that each elements appears in exactly two subsets. We can think of each element as an edge between the subsets, it's a classical point of view. If we see subsets as nodes, we can model the subsets choice by coloring nodes into two colors, "taken" or "non-taken".
If an element is initially off, we need to take exactly one of the subsets containing it. The corresponding edge should have endpoints with different color. If an element is initially on, we must take none or both subsets : endpoints with same color.
We recognize a sort of bipartition, obviously there are at most two correct colorings for each connected component: fixing the color of a node fix the color of all connected nodes.
Hence, the final answer is the sum for each component, of the size of the smaller side of the partition.
Since the answer exists for i=ni=n, there exists a such partition of the graph (into "red" and "blue" nodes). We can find it with usual dfs, and keep it for lower values of ii.
In order to compute all mimi efficiently, we start from a graph with no edges (i=0i=0), and we add edges with DSU, maintaining in each connected component the count of nodes in red side, and the count of nodes in blue side.
Now, how to deal with elements that appears in exactly one subset? They don't add any edge in the graph, but they force to take one of the sides of the connected component. To simulate this, we can use a special forced flag, or just fix the count of the other side to +∞+∞ (but be careful about overflow if you do that).
Final complexity : O((n+k)⋅α(k))O((n+k)⋅α(k)).
1290D - Coffee Varieties (hard version)
Easy version (constant 2)
Let's try to maintain representative positions for each value. In the beginning, when we know nothing, every position can be a potential representative.
We will call them alive positions, and using queries, we will try to kill some positions and ending up with exactly one alive position per value. The answer will be the number of alive positions.
Note that when we kill a position, there must be another alive position with the same value. The danger here is to compare a position to a dead position of the same value: we may end up killing the single representative of the value.
Create blocks of size k2k2, (or 11 if k=1k=1). Query 1,2,…,n1,2,…,n and kill the element if you get Yes answer. Each value has at least one alive occurrence, its leftmost one. Moreover, all equalities inside blocks are removed.
In order to remove equalities between blocks, compare all unordered pairs of blocks (for each pair, reset the memory, look all elements in the first one, then all elements in the second one, and kill elements in the second one for each Yes answer). Note that we don't need to compare adjacent blocks. The number of queries is a bit less than 2n2k2n2k.
Hard version (constant 1.5)
Querying 1,2,…,n1,2,…,n allowed us to compare pairs (i,i+1)(i,i+1) in a very efficient manner because we reuse the memory of the previous comparison. Let's try to generalize this.
Consider a complete graph where nodes are blocks. Comparing pairs of blocks can be seen as covering edges of the graph. We can take any elementary path (that doesn't pass through a node twice), reset the memory and explore blocks in the corresponding order (killing elements for each Yes answer).
Each path will require (number of edges+1)⋅k2(number of edges+1)⋅k2 queries. It's optimal to have disjoint paths (if a path goes through an already visited edge, we can split it there). Hence, we want to use a few disjoint paths to cover all edges.
A randomized DFS works experimentally well (constant around 1.21.2).
However, we can acheive constant 11 using the following zig-zag pattern: s→s−1→s+1→s−2→s+2→…s→s−1→s+1→s−2→s+2→….