#include<bits/stdc++.h>#define int long longusingnamespace std;constint N =1e6+7;constint mod =1e9+7;int t,n,m,k;int a[N],b[N];
vector<int> v1,v2;signedmain(){
cin>>t;while(t--){
cin>>n>>k;for(int i =0; i < n ; i ++) cin>>a[i];sort(a,a+n);int flag =1;if(a[n-1]> k){
flag =0;}if(flag){
cout<<"YES"<<endl;continue;}if(a[0]+a[1]<= k){
cout<<"YES"<<endl;}else{
cout<<"NO"<<endl;}}return0;}
#include<bits/stdc++.h>#define int long longusingnamespace std;constint N =1e6+7;constint mod =1e9+7;int t,n,m,k;int a[N],b[N];
vector<int> v1,v2;booldiv(string s1,string p){//cout<<s1<<" "<<p<<endl;if(s1.size()%p.size()==0){for(int i =0; i < s1.size(); i += p.size()){for(int j =0; j < p.size(); j ++){if(s1[i+j]!= p[j])returnfalse;}}returntrue;}returnfalse;}intgetgcd(string s1,string s2){
string tmp ="";int gcd =-1;for(int i =0; i < s1.size(); i ++){
tmp += s1[i];if(div(s1,tmp)&&div(s2,tmp)){
gcd = i+1;}}return gcd;}intGCD(int a,int b){if(a < b)swap(a,b);return b ==0? a :GCD(b,a%b);}intlcm(int a,int b){return a/GCD(a,b)*b;}signedmain(){
cin>>t;while(t--){
string s1,s2;
cin>>s1>>s2;int g =getgcd(s1,s2);if(g ==-1){
cout<<-1<<endl;}else{
string tmp = s1.substr(0,g);int lc =lcm(s1.size()/g,s2.size()/g);for(int i =0; i < lc ; i ++){
cout<<tmp;}
cout<<endl;}}return0;}
C. No More Inversions
题意:难以描述。给定一个a数组
a:1,2,3,…,k−1,k,k−1,k−2,…,k−(n−k) (k≤n<2k).
要找一个 p 排列(1-k 的排列)。排列的定义可以自行百度。然后根据a数组和p数组,可以生成一个b数组。 要求是,b数组中的逆序对数量不大于a数组中的逆序对数量,且字典序最大。b的生成规则是:以a数组为p的索引,到p中取数放到b数组中。即b[i] = p[ a[i] ],有点绕。a数组就是当下标用。如 a:[1,2,3,2],那么生成的b数组就是:
b:[ p[1],p[2],p[3],p[2] ] 。
思路:比赛的时候花了很久才看懂题意。然后懵逼了一会,然后开始找规律,然后发现了规律。a数组中的逆序对就是 k ,之后的数。如[1,2,3,4,3,2],就是[4,3,2],这一部分。生成的b数组的后半部分(左右对称的部分)就是[p[2],p[3],p[4],p[3],p[2]],可以发现,如果p数组就是有序的,那么生成的就是 23432,逆序对数量一定是等于a数组的,因为其实就是b数组等于a数组了,一模一样,但是,如果p中这部分值是逆序的,那么生成的就是 43234,逆序对数量也等于a数组!!。那么显然逆序排列是字典序最大的。所以答案就是这个东西了!前面不对称的部分不能改,改了逆序对就比a数组更多。可以尝试证明一下。
AC代码:
#include<bits/stdc++.h>#define int long longusingnamespace std;constint N =1e6+7;constint mod =1e9+7;int t,n,m,k;int a[N],b[N];
vector<int> v1,v2;signedmain(){
cin>>t;while(t--){
cin>>n>>k;int res = n-k;int tmp = k-res-1;for(int i =1; i <= tmp ; i ++){
cout<<i<<" ";}for(int i = k ; i > tmp ; i --){
cout<<i<<" ";}
cout<<endl;}return0;}
D. Program
题意:x,初始为0,两种操作,’+’ 表示 x += 1,’-’ 表示 x -= 1。然后题目给出一系列操作。然后q个询问 l,r。表示删掉区间 [l-r],之内的操作,剩下的操作,可以让x变成多少不同的值。
84-+--+--+18282511
样例解释:
1.empty program — x was only equal to 0;2."-" — x had values 0and −1;3."---+" — x had values 0, −1, −2, −3, −2 — there are 4 distinct values among them;4."+--+--+" — the distinct values are 1,0, −1, −2.
#include<bits/stdc++.h>#define int long longusingnamespace std;constint N =1e6+7;constint mod =1e9+7;int t,n,m,k;int a[N],b[N];int res[N];
vector<int> v1,v2;struct node{int maxx,minn,now;}seg[N],seg2[N];signedmain(){
cin>>t;while(t--){
cin>>n>>k;
string s;
cin>>s;int maxx =0;int minn =0;int now =0;for(int i =0; i < n ; i ++){// 从前往后维护 前半部分if(s[i]=='-') now -=1;if(s[i]=='+') now +=1;
maxx =max(maxx,now);
minn =min(minn,now);
seg[i].maxx = maxx;
seg[i].minn = minn;
seg[i].now = now;}
maxx =0;
minn =0;
now =0;for(int i = n-1; i >=0; i --){// 从后往前维护 后半部分if(s[i]=='-') now -=1;if(s[i]=='+') now +=1;
maxx =max(maxx,now);
minn =min(minn,now);
seg2[i].maxx = now-minn;
seg2[i].minn = now-maxx;
seg2[i].now =0;}// 防止 越界
seg[n].maxx = seg2[n].maxx =0;
seg[n].minn = seg2[n].minn =0;for(int i =0; i < k ; i ++){int x,y;
cin>>x>>y;x--,y--;x--,y++;int maxx =0;int minn =0;// 合并两个区间,计算最大值和最小值。因为前面可能为空。所以maxx,minn初始都为0。if(x >=0){
maxx =max(seg[x].maxx,seg[x].now+seg2[y].maxx);
minn =min(seg[x].minn,seg[x].now+seg2[y].minn);}else{
maxx = seg2[y].maxx;
minn = seg2[y].minn;}
res[i]= maxx-minn+1;}for(int i =0; i < k ; i ++){
cout<<res[i]<<endl;}}return0;}