zoukankan      html  css  js  c++  java
  • 【CometOJ】Comet OJ

    点此进入比赛

    (A):杀手皇后(点此看题面

    大致题意: 求字典序最小的字符串。

    一场比赛总有送分题。。。

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    using namespace std;
    int n;string s;
    int main()
    {
    	RI i;string st;for(cin>>n>>s,i=2;i<=n;++i) cin>>st,st<s&&(s=st,0);//读入,求字典序最小字符串
    	return cout<<s<<endl,0;//输出
    }
    

    (B):支援城市(点此看题面

    大致题意: 对于每个(x),求(sum_{i=1}^n(a_i-a_x)^2)

    拆平方得到:

    [sum_{i=1}^n(a_i^2-2a_ia_x+a_x^2)=sum_{i=1}^na_i^2-2a_xsum_{i=1}^na_i+na_x^2 ]

    不难发现,只要预处理出(sum_{i=1}^na_i^2)(sum_{i=1}^na_i),对于每个(x)就可以直接(O(1))计算了。

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define LL long long
    using namespace std;
    int n,a[N+5];
    int main()
    {
    	RI i;LL s=0,s2=0;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i),s+=a[i],s2+=1LL*a[i]*a[i];//预处理和及平方和
    	for(i=1;i<=n;++i) printf("%lld ",s2-2*s*a[i]+1LL*n*a[i]*a[i]);return 0;//计算答案并输出
    }
    

    (C):符文能量(点此看题面

    大致题意: 给你两个数组(a,b),可以选择一段区间([L,R]),使得(Lle ile R)的所有(a_i,b_i)都乘上(k),求(sum_{i=2}^nb_{i-1}a_i)的最小值。

    这可以直接(DP)

    我们设(f_i)表示选择包含(i)(i)不为结尾的一段区间所能得到的最小变化值。

    转移时分两种情况讨论,一种是(i)在区间内部,另一种是(i)为区间开头:

    [f_i=min(f_{i-1}+b_{i-1}a_i(k^2-1),b_{i-1}a_i(k-1)) ]

    同时我们每次要用以(i)为结尾的情况去更新最小变化值:

    [Mn=min(Mn,f_{i-1}+b_{i-1}a_i(k-1)) ]

    最终答案就是原先的答案加上最小变化值。

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define LL long long
    #define min(x,y) ((x)<(y)?(x):(y))
    #define Gmin(x,y) (x>(y)&&(x=(y)))
    using namespace std;
    int n,k,a[N+5],b[N+5];LL f[N+5];
    int main()
    {
    	RI i;LL Mn=0,ans=0;for(scanf("%d%d",&n,&k),i=1;i<=n;++i) scanf("%d%d",a+i,b+i);//读入
    	for(i=1;i<=n+1;++i) Gmin(Mn,f[i-1]+b[i-1]*a[i]*(k-1)),//更新最小变化值
    		ans+=b[i-1]*a[i],f[i]=min(b[i-1]*a[i]*(k-1),f[i-1]+b[i-1]*a[i]*(k*k-1));//计算原先答案,并动态规划转移f[i]
    	return printf("%lld",ans+Mn),0;//输出答案
    }
    

    (D):菜菜种菜(点此看题面

    大致题意: 给一张有向图,每次询问一个区间,求这个区间内不与区间内其他点直接相连的点的权值之和。

    我们定义(l_i)为与(i)相连的点中编号小于(i)的最大编号,(r_i)为与(i)相连的点中编号大于(i)的最小编号。

    设当前询问区间为([L,R]),那么一个点对一个询问有贡献,当且仅当其满足:

    [l_i<Lle ile R<r_i ]

    即:

    [l_i+1le Lle ile Rle r_i-1 ]

    那么我们就可以考虑离线,将询问对(L)排序。

    然后我们枚举(L),每次对于所有(l_i+1=L)(i),它们满足条件了,因此用树状数组维护,将(isim r_i-1)位置都加上(a_i)

    同时,(L-1)这个位置已不在询问范围内,因此我们把(L-1sim r_{L-1}-1)的位置都减去(a_{L-1})

    询问时只要询问(a_R)位置上的值即可。

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000000
    #define swap(x,y) (x^=y^=x^=y)
    #define Gmin(x,y) (x>(y)&&(x=(y)))
    #define Gmax(x,y) (x<(y)&&(x=(y)))
    using namespace std;
    int n,m,Qt,a[N+5],l[N+5],r[N+5],L[N+5],R[N+5];
    vector<int> s[N+5],q[N+5];vector<int>::iterator it;
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define tn (x<<3)+(x<<1)
    		#define D isdigit(c=tc())
    		char c,*A,*B,FI[FS];
    	public:
    		I FastIO() {A=B=FI;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
    		Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }F;
    class TreeArray//树状数组
    {
    	private:
    		#define lowbit(x) (x&-x)
    		int v[N+5];
    		I void Upt(RI x,CI y) {W(x<=n) v[x]+=y,x+=lowbit(x);}//修改后缀
    	public:
    		I void Add(CI l,CI r,CI v) {Upt(l,v),Upt(r+1,-v);}//区间修改,差分
    		I int Qry(RI x,RI t=0) {W(x) t+=v[x],x-=lowbit(x);return t;}//单点询问
    }T;
    int main()
    {
    	RI i,x,y;long long ans=0;
    	for(F.read(n,m,Qt),i=1;i<=n;++i) F.read(a[i]),l[i]=0,r[i]=n+1;//初始化
    	for(i=1;i<=m;++i) F.read(x,y),x>y?Gmax(l[x],y):Gmin(r[x],y);//预处理l,r
    	for(i=1;i<=n;++i) s[l[i]].push_back(i);//对于l[i]开桶,方便后面的操作
    	for(i=1;i<=Qt;++i) F.read(L[i],R[i]),q[L[i]].push_back(i);//读入询问,并桶排
    	for(i=1;i<=n;++i)//枚举L
    	{
    		i^1&&(T.Add(i-1,r[i-1]-1,-a[i-1]),0);//删去L-1的贡献
    		for(it=s[i-1].begin();it!=s[i-1].end();++it) T.Add(*it,r[*it]-1,a[*it]);//对于所有l[i]+1=L的i,加上其贡献
    		for(it=q[i].begin();it!=q[i].end();++it) ans^=1LL*(*it)*T.Qry(R[*it]);//枚举R询问
    	}return printf("%lld",ans),0;
    }
    

    (E):神奇函数(点此看题面

    大致题意: (d(x))(x)大于(1)的最小因数,(f(x)=egin{cases}1 & x=1\d(x)f(frac x{d(x)^2}) & d(x)^2|x\f(frac x{d(x)}) & othersend{cases}),求(sum_{i=1}^nf(i))

    我们设(x=sum_{i=1}^tp_i^{c_i}),则(f(x)=sum_{i=1}^tp_i^{lfloorfrac {c_i}2 floor})。证明如下:

    对于一个(p_i),若(c_ige 2),则由(f(x)=d(x)f(frac x{d(x)^2}) (d(x)^2|x))就会消掉(x)中的两个(p_i),得到(f(x))中的(1)(p_i),即(c_i)个数除以(2)

    而若(c_i=1),则由(f(x)=f(frac x{d(x)}) others)就会把这一个(p_i)消掉,即除以二后向下取整。

    那么,(f(n))显然是(O(sqrt n))级别的。

    所以我们可以枚举(f(i)),设(g(x))表示(1sim n)内不含平方因子的数的个数,那么答案就是:

    [sum_{i=1}^{sqrt n}icdot g(lfloorfrac n{i^2} floor) ]

    其中(g)的意义在于,若一个数含有平方因子(k^2),那么它的(f)值就会是(ik),所以应不含平方因子。

    然后考虑(g)值的求法,这可以使用容斥,而容斥系数就是(mu)。所以:

    [g(x)=sum_{i=1}^{sqrt x}mu(i)lfloorfrac n{i^2} floor ]

    对于上面的答案以及这里的(g),我们都可以用除法分块来较快速地求值,但似乎会被卡。。。

    所以我们要预处理出(xle10^7)(g(x)),这样就能过了。

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define LS 10000000
    #define LL long long
    using namespace std;
    LL n;
    template<int SZ> class LinearSieve//线性筛
    {
    	private:
    		int Pt,P[SZ+5],mu[SZ+5];
    	public:
    		LL smu[SZ+5],smu2[SZ+5];
    		I LinearSieve()
    		{
    			RI i,j;for(mu[1]=1,i=2;i<=LS;++i)
    				for(!P[i]&&(mu[P[++Pt]=i]=-1),j=1;j<=Pt&&1LL*i*P[j]<=SZ;++j)
    					if(P[i*P[j]]=1,i%P[j]) mu[i*P[j]]=-mu[i];else break;
    			for(i=1;i<=LS;++i) smu[i]=smu[i-1]+mu[i],smu2[i]=smu2[i-1]+mu[i]*mu[i];//筛mu和以及平方和
    		}
    };LinearSieve<LS> L;
    I LL G(Con LL& x)
    {
    	if(x<=LS) return L.smu2[x];RI l,r,sx=sqrt(x);LL res=0;//x较小时直接返回答案
    	for(l=1;l<=sx;l=r+1) r=sqrt(x/(x/(1LL*l*l))),res+=x/(1LL*l*l)*(L.smu[r]-L.smu[l-1]);//除法分块
    	return res;//返回答案
    }
    int main()
    {
    	RI Tt,l,r,sn;LL ans=0;scanf("%d",&Tt);W(Tt--)
    	{
    		scanf("%lld",&n),sn=sqrt(n),ans=0;//读入
    		for(l=1;l<=sn;l=r+1) r=sqrt(n/(n/(1LL*l*l))),ans+=G(n/(1LL*l*l))*(l+r)*(r-l+1)>>1;//除法分块
    		printf("%lld
    ",ans);//输出答案
    	}return 0;
    }
    

    (F):黄金体验(占坑待填)

  • 相关阅读:
    事务传播机制,搞懂。
    洛谷 P1553 数字反转(升级版) 题解
    洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here 题解
    洛谷 P1055 ISBN号码 题解
    洛谷 P2141 珠心算测验 题解
    洛谷 P1047 校门外的树 题解
    洛谷 P1980 计数问题 题解
    洛谷 P1008 三连击 题解
    HDU 1013 题解
    HDU 1012 题解
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CometOJContest8.html
Copyright © 2011-2022 走看看