传送门:然而并没有...
这两天测试状态比较奇怪,前面1.5h-2h完全不知所措,一脸茫然,感觉自己吃枣药丸
后面才发现有很多题可捉的,并没有想象的那么难,但是时间已经不充裕了...
R2D2
T1:不知所措数学题
一开始总想着有什么DP可以拿一些部分分
然而连30分DP都不会....
咦,好像有大样例
那就找一发规律
妈呀真是2^(nk)
快速幂完事....
考完冷静了一下发现还是比较容易证的
首先n位每位相互独立,所以可以只考虑一位
设f[k]表示k*k的三角形的方案数
考虑f[k+1]怎么递推
如果最左下角的数是0,那么最后一行已经确定了,都会是0
而且不会对上面的k*k的三角形有影响,所以方案数是f[k]
如果是1,同理,最左边一行已经确定了,都必须是1
而且也不会对右边的k*k的三角形有影响,所以方案数是f[k]
所以f[k+1]=2*f[k]
所以一位的答案就是2^k
n位乘起来就好了,答案就是2^(nk)
T2:数据结构题?
一看到这题我就觉得是数据结构题,然而想来想去并不知道怎么维护....于是弃疗了
后来我才发现一个显然的性质
就是最大和最小一定取在端点,不然不是最优
然后我们就可以分数规划了
情况有点多
假设i是右端点,j是左端点
假设a[i]为max,a[j]为min
那么(a[i]-a[j])/(i-j+K)=ans
变形得(a[i]-i*ans)-(a[j]-j*ans)=k*ans
所以我们二分一下ans,有满足左边大于右边的,ans就可以更大
左边最大值可以用单调队列做
记A[i]=a[i]-ans*i
如果后面加进来的A[i]比队尾要小,队尾就没有意义了,可以删去
对于区间长度是[L,R]的限制,初始时保持距离为L,加入队列时从队头删去距离超过R-1的点即可
反过来类似,注意一些细节
另外就是区间长为L时
类似地,(a[i]-a[j])/(L-1+K)=ans
变形得:a[i]-a[j]=ans*(L-1+K)
也是二分,单调队列维护即可
复杂度O(nlogmaxans)
T3:字符串神题?
突然发现字符串长<=10.....
拿个可持久化trie维护一下就好了
儿子节点从父亲节点继承trie,再把边上的字符串插入进去即可
每次用ans[x]+ans[y]-2*ans[lca]即可
R3D1
T1:一开始想到了一个玄学做法,好像很复杂的样子...然后就安心打暴力去了
后来证了一下发现是对了,加个bitset好像可以卡过
我们对于每个点求出它能到哪些点,记为g[i][maxn],这个可以压位做到m*n/32
然后对于每个点v,处理哪些连向它的边可删
如果一个它的前驱x能够到它的另一个前驱y
那么显然x连向它的边可以删去了
然后证明没有其他可删的边
假设有一个边可删,且不满足上面的条件
那么说明x到v有其他路径
那么这条路经一定要经过v的另一个前驱z,那么x可以到z,不符假设
所以不存在这样的边
具体实现就对每个点求一个bitset,表示是否是x的前驱
在把它和每个前驱的g[i]and一下,如果有1,就说明可以从其他点过来,然后就可以删掉这条边
然后发现有点卡常,怕70分都没了,于是只开到1000,70保平安...
然后发现标程压64位.....
T2:神奇的插头DP
妈呀200*200....
一定有特殊的DP方法
D了半天不知所措....
突然发现这是很简单的网络流,每栋房子是一个点,源向它连卖给A的权值,它向汇连卖给B的的权值,相邻的点连建围墙的权值,求出最小割,拿总收益减去就是了...
然后就是15分钟写网络流系列...
然后就爆零被教做人了...
T3:这个真是字符串神题,看了标程好像是后缀数组,暴力还挂了,不知所措...
得分情况:100+0+100+70+0+0
有些题目就是要敢于去想,要相信能写出来
但是有时写暴力求稳也是很重要的...
R2D1
T1:
#include
#include
#include
#include
typedef long long ll;
const ll mod=(ll)1e9+7;
using namespace std;
int n,k;
ll qpow(int a,ll b){
ll res=1,j=a;
while (b){
if (b&1) res=res*j%mod;
j=j*j%mod,b>>=1;
}
return res;
}
int main(){
scanf("%d%d",&n,&k);
printf("%lld\n",qpow(2,1ll*n*k));
return 0;
}
T2:
#include
#include
#include
#include
#include
const double eps=1e-6;
const int maxn=100010;
using namespace std;
int cas,a[maxn],n,K,L,R;
struct Tque{
int pos[maxn],head,tail;double val[maxn];
void clear(){head=1,tail=0;}
void pushmin(int p,double v){
//maximize a[i]-miu*i-a[j]+miu*j
//if A[j]<=A[q[tail]]
//because j>q[tail]
//j is better than q[tail]
while (head<=tail&&v<=val[tail]) tail--;
val[++tail]=v,pos[tail]=p;
}
void pushmax(int p,double v){
while (head<=tail&&v>=val[tail]) tail--;
val[++tail]=v,pos[tail]=p;
}
void pop1(int p){while (head<=tail&&p-pos[head]+1>R) ++head;assert(p-pos[head]+1<=R);}
void pop2(int p){while (head<=tail&&pos[head]=p-L+1);}
double top(){return val[head];}
}q;
bool check(double miu){
q.clear();
for (int i=L;i<=n;i++){
int j=i-L+1;
q.pushmin(j,a[j]-j*miu),q.pop1(i);
if (a[i]-miu*i-q.top()+eps>=K*miu) return 1;
}
q.clear();
for (int i=L;i<=n;i++){
int j=i-L+1;
q.pushmax(j,a[j]+j*miu),q.pop1(i);
if (q.top()-a[i]-miu*i+eps>=K*miu) return 1;
}
q.clear();
for (int i=1;i<=n;i++){
q.pushmin(i,a[i]),q.pop2(i);
if (a[i]-q.top()+eps>=(L-1+K)*miu) return 1;
}
q.clear();
for (int i=1;i<=n;i++){
q.pushmax(i,a[i]),q.pop2(i);
if (q.top()-a[i]+eps>=(L-1+K)*miu) return 1;
}
return 0;
}
int main(){
//freopen("gift.in","r",stdin);freopen("gift.out","w",stdout);
scanf("%d",&cas);
while (cas--){
scanf("%d%d%d%d",&n,&K,&L,&R);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
double l=0.0,r=1000.0,mid=500.0;
while (r-l>eps){
if (check(mid)) l=mid;
else r=mid;
mid=(l+r)/2;
}
printf("%.4lf\n",l);
}
return 0;
}
/*
1
5 1 2 4
1 2 3 4 5
*/
T3:
#include
#include
#include
#include
const int maxn=100010,maxm=200010,maxt=1200010;
using namespace std;
int n,Q,pre[maxm],now[maxn],son[maxm],val[maxm][15],tot,pp[15],fa[maxn][22],dep[maxn];char tmp[15];
struct Trie{
int root[maxn],ch[maxt][28],tot,cnt[maxt];
void insert(int now,int pre,int s[]){
int len=0;
while (s[len+1]) len++;
//for (int i=1;i<=len;i++) printf("%d ",s[i]);puts("s[i]");
for (int i=1;i<=len;i++){
for (int j=1;j<=26;j++){
if (j==s[i]) ch[now][j]=++tot,cnt[tot]=cnt[ch[pre][j]]+1;
else ch[now][j]=ch[pre][j];
}
now=ch[now][s[i]],pre=ch[pre][s[i]];
}
for (int j=1;j<=26;j++) ch[now][j]=ch[pre][j];
}
int query(int now,int s[]){
for (int i=1;s[i];i++) now=ch[now][s[i]];//,printf("now=%d s[i]=%d cnt=%d\n",now,s[i],cnt[now])
//puts("\n");
return cnt[now];
}
}T;
void add(int a,int b){
pre[++tot]=now[a],now[a]=tot,son[tot]=b;
for (int i=1;pp[i];i++) val[tot][i]=pp[i];
}
void dfs(int x){
for (int i=1;i<=19;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for (int y=now[x];y;y=pre[y]) if (son[y]!=fa[x][0]){
T.root[son[y]]=++T.tot,T.insert(T.root[son[y]],T.root[x],val[y]);
dep[son[y]]=dep[x]+1,fa[son[y]][0]=x,dfs(son[y]);
}
}
int lca(int a,int b){
if (dep[a]=0;i--)
if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
return fa[a][0];
}
void change(){
int len=strlen(tmp+1);
memset(pp,0,sizeof(pp));
for (int i=1;i<=len;i++) pp[i]=tmp[i]-'a'+1;
}
int main(){
freopen("strings.in","r",stdin);freopen("strings.out","w",stdout);
scanf("%d",&n);
for (int i=1,x,y;i
R3D1
T1:这个程序只能过70分,但是是标算,还要特殊的卡常数技巧(标程是压64位,可能在64位机上要快一些就过了)
#include
#include
#include
#include
#include
const int maxn1=18,maxn=30010,maxm=100010;
using namespace std;
struct Edge{int x,y;}E[maxm];
bitset map[maxn];
int n,m,ans,pw[maxn1],ord[maxn];bool g[maxn1][maxn1],con[maxn1][maxn1],tmp[maxn1][maxn1],bo[maxn1];
struct Twork1{
void dfs(int x){
bo[x]=1;
for (int i=1;i<=n;i++) if (g[x][i]&&!bo[i]) dfs(i);
}
bool check(int s){
memset(g,0,sizeof(g)),memset(tmp,0,sizeof(tmp));
for (int i=0;i tmp;
int ans=0;
for (int x=1;x<=n;x++){
tmp.reset();
for (int y=now[x];y;y=pre[y])
tmp[son[y]]=1;
for (int y=now[x];y;y=pre[y])
if ((tmp&map[son[y]]).any()) ans++;
}
printf("%d\n",ans);
}
}T2;
int main(){
freopen("graph.in","r",stdin);freopen("graph.out","w",stdout);
pw[0]=1;for (int i=1;i<=16;i++) pw[i]=pw[i-1]<<1;
scanf("%d%d",&n,&m);
if (n<=15&&m<=15) T1.work();
else T2.work();
return 0;
}
/*
5 6
1 2
2 3
3 5
4 5
1 5
1 3
7 8
1 2
2 5
5 7
1 3
6 7
1 4
4 7
3 5
*/
T2:
#include
#include
#include
#include
#include
#define aabs(a) (a>0?a:-(a))
const int maxn=500010,maxm=1000010,inf=(int)1e9;
using namespace std;
int n,m,ans,pre[maxm],now[maxn],son[maxm],val[maxm],tot,dis[maxn],head,tail,q[maxm+10];
int id(int x,int y){return (x-1)*m+y;}
struct Flow{
int S,T;
void add(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
void ins(int a,int b,int c){add(a,b,c),add(b,a,0);assert(totmaxn) head=1;
int x=q[head];
for (int y=now[x];y;y=pre[y])
if (val[y]&&dis[son[y]]==-1){
if (++tail>maxn) tail=1;
dis[son[y]]=dis[x]+1,q[tail]=son[y];
}
}
return dis[T]>0;
}
int find(int x,int low){
if (x==T) return low;
int y,res=0;
for (y=now[x];y;y=pre[y]){
if (dis[son[y]]!=dis[x]+1||!val[y]) continue;
int tmp=find(son[y],min(low,val[y]));
res+=tmp,low-=tmp,val[y]-=tmp,val[y^1]+=tmp;
if (!low) break;
}
if (!y) dis[x]=-1;
return res;
}
void work(){
int res=0;
while (bfs()) res+=find(S,inf);
printf("%d\n",ans-res);
}
}F;
void init(){
scanf("%d%d",&n,&m),F.clear();
for (int i=1;i<=n;i++)
for (int j=1,v;j<=m;j++){
scanf("%d",&v),ans+=aabs(v);
if (v>=0) F.ins(F.S,id(i,j),v);
else F.ins(id(i,j),F.T,-v);
}
for (int i=1;i
T3:不知所措....