2018 Multi-University Training Contest - Team 1 题解

SolvedAHDU 6298Maximum Multiple
SolvedBHDU 6299Balanced Sequence
SolvedCHDU 6300Triangle Partition
SolvedDHDU 6301Distinct Values
 EHDU 6302Maximum Weighted Matching
 FHDU 6303Period Sequence
SolvedGHDU 6304Chiaki Sequence Revisited
SolvedHHDU 6305RMQ Similar Sequence
 IHDU 6306Lyndon Substring
 JHDU 6307Turn Off The Light
SolvedKHDU 6308Time Zone

A  找规律

发现只有3和4的倍数有存在答案

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")

using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
ll casn,n,m,k;
#define tpyeinput ll
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);}
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	read(casn);
    while(casn--){
        read(n);
        if(n>=3&&n%3==0) printf("%lld\n",((n/3ll)*(n/3ll)*(n/3ll)));
        else if(n>=4&&n%4==0) printf("%lld\n",n*n*n/32ll);
        else puts("-1");
    }

#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

B 贪心

去掉已经配对的,对于剩下 的,左边括号>右括号的放在左边,如果同样是左括号>右括号,不需要管哪个左括号多,只需要管哪个右括号少,右括号少的放在左边

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);}
string str[maxn];
struct node {
	int a,b;
}s[maxn];
int cmp(node &a,node &b){
	int x=min(a.a,b.b),y=min(a.b,b.a);
	return x>y||x==y&&a.a>b.a;
}
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	IO;
	cin>>casn;
	while(casn--){
		cin>>n;
		rep(i,1,n){
			cin>>str[i];
		}
		int ans=0;
		rep(i,1,n){
			int a=0,b=0;
			rep(j,0,str[i].size()-1){
				if(str[i][j]=='(') a++;
				else if(str[i][j]==')'){
					if(a>0) a--,ans+=2;
					else b++;
				}
				s[i]=(node){a,b};
			}
		}
		sort(s+1,s+1+n,cmp);
		int a=0,b=0;
		rep(i,1,n){
			if(a>=s[i].b){
				ans+=s[i].b*2;
				a-=s[i].b;
			}else {
				ans+=a*2;
				a=0;
			}
			a+=s[i].a;
		}
		cout<<ans<<endl;
	}
#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

C 画图,找规律

保证三点不共线,画图尝试之后发现规律,把点排序即可(这道题用输入挂反而会WA?)

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
//#define tpyeinput int
//inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
//inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
//inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);}
//inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);}
//inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);}
struct node {
	int x,y,id;
}p[maxn];
bool cmp(node &a,node& b){
	if(a.x==b.x) return a.y<b.y;
	return a.x<b.x;
}
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	IO;
	cin>>casn;
	while(casn--){
		cin>>n;
		rep(i,1,3*n){
			int a,b;
			cin>>a>>b;
			p[i]=(node){a,b,i};
		}
		sort(p+1,p+1+3*n,cmp);
		k=1;
		rep(i,1,n){
			rep(j,1,3){
				cout<<p[k++].id<<' ';
			}
			cout<<endl;
		}
	}
#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

D 双指针/贪心+小根堆维护mex

排序要求的区间,然后双指针遍历所有即可,用priority_queue维护当前双指针内的mex

卡时间,建议上输入挂

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
int casn,n,m,k;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);}
int ans[maxn];
int pos[maxn];
set<int>num;
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	read(casn);
	while(casn--){
		read(n,m);
		rep(i,1,n) {
			ans[i]=1;
			pos[i]=i;
			num.insert(i);
		}
		rep(i,1,m){
			int a,b;
			read(a,b);
			pos[b]=min(pos[b],a);
		}
		for(int i=n-1;i;i--){
			pos[i]=min(pos[i],pos[i+1]);
		}
		int last=1;
		rep(i,1,n){
			while(last<pos[i]){
				num.insert(ans[last]);
				last++;
			}
			ans[i]=*num.begin();
			num.erase(ans[i]);
		}
		rep(i,1,n){
			printf("%d%c",ans[i]," \n"[i==n]);
		}
	}

#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

G 找规律+打表倍增

找规律发现,数列中$X$的出现次数是$lowbit(X)$,于是对于出现次数相同的值(也就是$lowbit(x)$相同)的数,构成了等差数列..

原数列就是很多个等差数列构成的了,然后先预处理一下值,每次有多少个不同的等差数列,求和即可...

具体看代码

#include <bits/stdc++.h>
#define ll long long
#define show(x) cout<<#x<<"="<<x<<endl
#define show2(x,y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl
#define show3(x,y,z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show4(w,x,y,z) cout<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define show5(v,w,x,y,z) cout<<#v<<" "<<v<<" "<<#w<<"="<<w<<" "<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl
#define showa(a,b) cout<<#a<<'['<<b<<"]="<<a[b]<<endl
#define print(x) cout<<#x<<"="<<x<<' '
#define ptline() cout<<endl
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const ll mod=1e9+7;
const int INF=0x3f3f3f3f;
ll casn,n,m,k;
#define tpyeinput ll
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);}
ll num[maxn],p[maxn];
ll inv=(mod+1)/2;
void init(){
	num[0]=p[0]=1;
	rep(i,1,63){
		num[i]=num[i-1]*2ll+1ll;
		p[i]=p[i-1]*2ll;
	}
}
ll cal(ll pos){
	ll sum=0;
	for(ll i=1;i<=pos;i*=2ll){
		ll num=(pos-i)/(2*i);
		ll m=i+num*(2ll*i);;
		num=(num+1ll)%mod;
		m=(m+i)%mod;
		m=m*num%mod;
		m=m*inv%mod;
		m=m*(__builtin_ctz(i)+1ll)%mod;
		sum=(sum+m)%mod;
	}
	return (sum+1)%mod;
}
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	read(casn);
	init();
	while(casn--){
		read(n);
		n--;
		if(!n){
			puts("1");
			continue;
		}
		ll tmp=n;
		ll pos=0;
		for(int i=62;i>=0;i--){
			if(tmp>=num[i]){
				tmp-=num[i];
				pos+=p[i];
			}
		}
		ll sum=cal(pos);
		if(tmp){
			sum=(sum+tmp%mod*(pos+1ll)%mod)%mod;
		}
		printf("%lld\n",sum);
	}
#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

H 组合数学+笛卡尔树性质

笛卡尔树的2个重要性质,

1.中序遍历等于原序列,换句话说,就是把树拍扁等价于原数列

2.区间的最大元素,就是表示了这个区间的子树的根节点

放到这个题里,就是笛卡尔树的形状和题目给的一样,问你多少种...

组合数学,dfs笛卡尔树记算总种类数,过程中需要求逆元...

代码里的这个笛卡尔树和线性推逆元是学的dls..

推导参考出题大爷:

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e6+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
inline void read(tpyeinput &num1,tpyeinput &num2){read(num1);read(num2);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){read(num1);read(num2);read(num3);}
inline void read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){read(num1);read(num2);read(num3);read(num4);}
int casn,n,m,k;
struct node{int l,r;}ctree[maxn];
ll inv[maxn],ans;
int stk[maxn],vis[maxn];
pair<int,int> num[maxn];
#define nd ctree[now]
int dfs(int now){
	if(now==0)return 0;
	int sum=dfs(nd.l)+dfs(nd.r)+1;
	ans=ans*inv[sum]%mod;
//	cout<<ans<<endl;
	return sum;
}
void maketree(){
	int top=0;
	rep(i,1,n){
		int now=top;
		while(now&&num[stk[now-1]]>num[i]) now--;
		if(now) ctree[stk[now-1]].r=i;
		if(now<top) ctree[i].l=stk[now];
		stk[now++]=i;
		top=now;
	}
}
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
	inv[1]=1;
	rep(i,2,maxn-5)inv[i]=inv[mod%i]*(mod-mod/i)%mod;
	read(casn);
	while(casn--){
		read(n);
		rep(i,1,n){
			int x;
			read(x);
			num[i]=make_pair(-x,i);
		}
		ans=inv[2]*(ll)n%mod;
//		cout<<ans<<endl;
		rep(i,1,n) ctree[i]=(node){0,0},vis[i]=0;
		maketree();
		rep(i,1,n) vis[ctree[i].l]=vis[ctree[i].r]=1;
		int rt=0;
		rep(i,1,n) if(vis[i]==0) {
			rt=i;break;
		}
		dfs(rt);
		printf("%lld\n",ans);
	}
#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

K 模拟题

难点有2个

输入,误差..

输入建议用"scanf("%d %d UTC%c%lf",&h,&m,&flag,&utc);";

    也可以"cin>>h>>m>>ch>>ch>>ch>>ch>>utc";

误差就是$1.4$会被读入为$1.39999$取整变成$1.3$之类的

utc+=0.001就行了,消除误差,而且不影响答案

#include <bits/stdc++.h>
#define ll long long
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(ii,a,b) for(int ii=a;ii<=b;ii++)
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,m,k;
int main(){
//#define test
#ifdef test
  freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#endif
    scanf("%d",&casn);
    int h,m,flag,ch,x;
    double y;
    while(casn--){
        y=0;
        double tt;
        scanf("%d %d UTC%c%lf",&h,&m,&flag,&tt);
        tt+=0.0001;
        x=(int)tt;
        y=tt-x;
        y*=10;
        if(flag=='-') {
        x=-(x+8);
        y=-y;}
        else x-=8;
        int t1=x;
        int t2=y*6;
        h+=t1;
        m+=t2;
        if(m>=60){
            m-=60;
            h++;
        }
        if(h>=24) h-=24;
        if(m<0){
            m+=60;
            h--;
        }if(h<0){
            h+=24;
        }
        printf("%02d:%02d\n",h,m);
    }

#ifdef test
  fclose(stdin);fclose(stdout);system("out.txt");
#endif
  return 0;
}

  

转载于:https://www.cnblogs.com/nervendnig/p/9365002.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值