2018 Multi-University Training Contest - Team 1 題解

Solved A HDU 6298 Maximum Multiple
Solved B HDU 6299 Balanced Sequence
Solved C HDU 6300 Triangle Partition
Solved D HDU 6301 Distinct Values
  E HDU 6302 Maximum Weighted Matching
  F HDU 6303 Period Sequence
Solved G HDU 6304 Chiaki Sequence Revisited
Solved H HDU 6305 RMQ Similar Sequence
  I HDU 6306 Lyndon Substring
  J HDU 6307 Turn Off The Light
Solved K HDU 6308 Time Zone

A  找規律node

發現只有3和4的倍數有存在答案ios

#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 貪心c++

去掉已經配對的,對於剩下 的,左邊括號>右括號的放在左邊,若是一樣是左括號>右括號,不須要管哪一個左括號多,只須要管哪一個右括號少,右括號少的放在左邊oop

#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 畫圖,找規律ui

保證三點不共線,畫圖嘗試以後發現規律,把點排序便可(這道題用輸入掛反而會WA?)spa

#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.net

排序要求的區間,而後雙指針遍歷全部便可,用priority_queue維護當前雙指針內的mex指針

卡時間,建議上輸入掛code

#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 找規律+打表倍增blog

找規律發現,數列中$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;
}
相關文章
相關標籤/搜索