【20171029校内模拟赛】无题

T1 时限1s,其余0.5s,运行内存上限64MB.不开启任何优化,评测机运行效率约为4e8.


T1 买(buy)

Description

LGL帮n个人买东西,有m个物品给他选择。每件物品有一个价格c[i]和美丽度d[i]。每一个人都只需要买一个物品,但是他们都很挑剔并且奢侈,第i个人需要买的东西的价格大等于a[i],美丽度大等于b[i]。每个物品只能买给一个人,请问LGL最少要花多少钱?如果无法全部满足,输出-1。

Input

第一行为两个整数n、m,接下来的n行每行两个整数a[i]、b[i],再接下来的m行每行两个整数c[i]、d[i]。

Output

一个整数,表示LGL最少花钱数。

Sample Input

4 7
1 1
2 3
1 4
4 2
3 2
2 1
4 3
5 2
5 4
2 6
4 4

Sample Output

12

Hint

样例解释

物品
1 2
2 3
3 6
4 7

数据规模

对于100%的数据:\(1 \leq n,m \leq 100000\)\(1 \leq 其他数字 \leq 10^9\)

Solution

考虑按美丽度从大到小排序,用< set > 维护美丽度比当前人大的的价格,查询的时候找lower_bound即可,时间复杂度\(O((n+m)\log (n+m))\)

Code

#include <stdio.h>
#include <algorithm>
#include <set>
#define R register
#define MN 100005
#define ll long long
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
inline int read(){
    R int x; R bool f; R char c;
    for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
    for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
    return f?-x:x;
}
struct sth{
    int c,v;
    inline bool operator <(const sth &b)const{
        return v>b.v;
    }
}per[MN],th[MN];
int n,m;ll ans;
std::multiset<int> s;
std::multiset<int>::iterator it;
int main(){
    file(buy);n=read(),m=read();
    for (R int i=1; i<=n; ++i)
        per[i].c=read(),per[i].v=read();
    for (R int i=1; i<=m; ++i)
        th[i].c=read(),th[i].v=read();
    std::sort(per+1,per+n+1);std::sort(th+1,th+m+1);
    for (R int i=1,j=1; i<=n; ++i){
        while(j<=m&&per[i].v<=th[j].v) s.insert(th[j++].c);
        it=s.lower_bound(per[i].c);
        if (it==s.end()){
            puts("-1");
            return 0;
        }ans+=*(it);s.erase(it);
    }printf("%lld\n",ans);
}

T2 加密(password)

Description

LGL找了n个人来加密一个含有n个数字的密码。他的方法是:找n个人记住每一个数字c[i],然后每个人计算其他人的数字之和mod 98765431作为加密后的密码。但是ditoly只用了5秒钟就算出了他的密码,这让他十分气馁。于是他要用更高级的加密方式:即做上述过程x次。LGL想看看ditoly现在要多少秒才能算出来,所以他请你帮他算出加密后的n个数字。

Input

第一行为两个整数n、x,接下来n行每行一个整数c[i]。

Output

n行,每行一个整数,表示加密后的每一个数。

Sample Input

3 4
1
0
4

Sample Output

26
25
29

Hint

对于100%的数据:1<=n<=50000,1<=x<=1414213562,1<=c[i]<=90000000。

Solution

发现每次结果一定含有+/- vi 然后,去掉vi以后结果记为ai的话,容易写出递推式:\(ai=(n-1)ai-1+(-1)^{(i-1)} \Sigma vj\)
容易构造出矩阵,然后快速幂即可,时间复杂度\(O(n).\)

Code

#include <stdio.h>
#include <string.h>
#define R register
#define MN 50005
#define mod 98765431
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
#define end fclose(stdin);fclose(stdout)
inline int read(){
	R int x; R bool f; R char c;
	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
	return f?-x:x;
}
struct mat{
	int a[2][2];
	inline void clear(){memset(a,0,sizeof(a));}
	mat operator*(const mat &b)const{
		mat c;c.clear();
		for (R int i=0; i<2; ++i)
			for (R int j=0; j<2; ++j)
				for (R int k=0; k<2; ++k)
					c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j])%mod,c.a[i][j]+=mod,c.a[i][j]>=mod?c.a[i][j]-=mod:0;
		return c;
	}
}modify,fir,ans;
inline mat pw(mat a,int k){
	mat p;p.clear();for (R int i=0; i<2; ++i) p.a[i][i]=1;
	for (; k; a=a*a,k>>=1) if (k&1) p=p*a;
	return p;
}
int n,x,v[MN],sum;
int main(){
	file(password);n=read();x=read();modify.clear();
	modify.a[0][0]=n-1,modify.a[1][0]=n-1,modify.a[1][1]=-1,modify.a[0][1]=0;modify=pw(modify,x-1);
	for (R int i=1; i<=n; ++i) v[i]=read()%mod,sum+=v[i],sum>=mod?sum-=mod:0;
	for (R int i=1; i<=n; ++i){
		fir.clear();fir.a[0][0]=0,fir.a[0][1]=sum;ans=fir;
		ans=fir*modify;ans.a[0][0]+=(x&1)?(sum-v[i]):(v[i]-sum);
		ans.a[0][0]=(ans.a[0][0]%mod+mod)%mod;printf("%d\n",ans.a[0][0]);
	}end;return 0;
}

T3 花费 (cost)

Description

LGL进入他的豪宅需要密码。他的密码长度为m,并且由n个不同字母构成。现在他想把密码改成回文的,他可以在任意位置添加或删除字母,而第i个字母都有不同的添加花费a[i]和删除花费b[i]。请问LGL最少要花多少钱才能把密码改成回文的?

Input

第一行为两个整数n、m,接下来的n行每行一个字母和两个数a[i]和b[i],表示该字母的添加花费和删除花费。

Output

一个整数,表示最小花费。

Sample Input

3 4
abcb
a 1000 1100
b 350 700
c 200 800

Sample Output

900

Hint

样例解释

变成了bcbabcb。

数据规模

对于100%的数据:1<=m<=2000、1<=n<=26,0<=a[i]、b[i]<=10000。

Solution

显然添加字母与删除字母是没有区别的,容易写出区间DP,dp方程为:$$f[l][r]={min(f[l+1][r]+v[l],f[l][r-1]+v[r]) (s[l] != s[r]); f[l+1}r-1$$

Code

#include <stdio.h>
#define MN 2005
#define R register
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
#define end fclose(stdin);fclose(stdout)
inline int read(){
	R int x; R bool f; R char c;
	for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
	for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
	return f?-x:x;
}
int f[MN][MN],v[52],n,m;char s[MN];
inline int min(int a,int b){return a<b?a:b;}
inline int getv(char c){return c>'Z'?c-'a'+26:c-'A';}
int main(){
	file(cost);n=read(),m=read();scanf("%s",s+1);
	for (R int i=0; i<52; ++i) v[i]=10001;
	for (R int i=1; i<=n; ++i){
		R char c=getchar();while((c<'a'||c>'z')&&(c<'A'||c>'Z')) c=getchar();
		v[getv(c)]=min(v[getv(c)],min(read(),read()));
	}for (R int i=1; i<=m; ++i) f[i][i]=0;
	for (R int l=2; l<=m; ++l)
		for (R int i=1,j; i<=m-l+1; ++i){
			if (s[i]==s[j=i+l-1])
				f[i][j]=f[i+1][j-1];
			else f[i][j]=min(f[i+1][j]+v[getv(s[i])],f[i][j-1]+v[getv(s[j])]);
		}printf("%d",f[1][m]);end;return 0;
}
posted @ 2017-10-30 09:37  Melacau  阅读(148)  评论(0编辑  收藏  举报