随笔 - 188  文章 - 0  评论 - 59  阅读 - 7707

模拟3

复制代码
复制代码
T3.tire树或者map映射,第一种高效10倍,待会再理解
#include<bits/stdc++.h> using namespace std; const int maxn = (1e4+10)*50; int tree[maxn][26],v[maxn][26],cnt[maxn][26],len,tot; char s[26]; void add(int l, int r, int id){ int rt = 0,t; while(l < r){//因为要看是否存在于字符串中而不是 是否为前缀 所以要把一个字符串以每个字符为起点存一次 t = s[l] - 'a';//将字母转化为对应的下标 if (tree[rt][t]) {//如果当前的字母已经建过节点 if (v[rt][t] != id) { v[rt][t] = id; ++cnt[rt][t];//当前字符串++ } } else {//如果还没有建过当前节点 tree[rt][t] = ++tot;//新建一个点 v[rt][t] = id; cnt[rt][t]++; } rt = tree[rt][t]; ++l; } } int search(){ int rt = 0,ans = 0; for(int i = 0;i < len;++i){ if(!tree[rt][s[i]-'a'])return 0;//如果当前字符未出现过 ans = cnt[rt][s[i]-'a'];//即为当前字符串出现的次数 rt = tree[rt][s[i]-'a'];//为下一次转移做准备 } return ans; } int main(){ freopen("mdz.in","r",stdin); freopen("mdz.out","w",stdout); int n;scanf("%d",&n); for(int i = 0;i < n;++i){ scanf("%s",s); len = strlen(s); for(int j = 0;j < len;++j){ add(j,len,i); } } int m;scanf("%d",&m); while(m--){ scanf("%s",s); len = strlen(s); printf("%d\n",search()); } }
复制代码

 


C. SSY的队列 - 高一普及组模拟赛3 - 比赛 - 衡中OI (hszxoj.com)
方法:状态压缩
+hash+dfs+记忆化 思路: 首先想到容斥原理,用所有的方案减去一个相同挨着的+两个相同挨着的,但是去重太麻烦,而且各个方案之间相互牵连,不方便实现
那么再仔细看题,可不可以对问题进行简化?
相邻的数差值是m的倍数,那全部摸上m,其实就是余数相同的不能放在一起
问题就抽象成了(3个red,5个blue,7个green排列相同颜色不挨着的方案数),深搜
dfs(dep,lst)第几个位置,上一个哪个种类,O(n^n)超时
发现,如果我知道当前lst组还剩下的人数,接下来还可以用的组别剩的人数分别有几组,我就可以从上面已求出状态转移过来
这个记忆化相当于大大减少了时复杂度O(n^n-相当多的一部分)
1处处特殊处理
const int N=40; const ll mod=1234567891,base=33; int a[N],b[N],c[N],mx,cnt; map<ll,ll>dp[N];//数组开不下 int n,m; ll fac[N]; inline ll dfs(int dep,int lst) { if(dep>n)return 1; memset(b,0,sizeof(b)); _f(i,1,cnt)//0不用算吧?至少不能一起算 { if(i!=lst)b[c[i]]++; } ll st=c[0];//b[i]=j,剩余人数是i的组有j个 _f(i,1,mx)//剩余人数是0个的组数我压根就没算 { st=st*base+b[i]; } st=st*base+((lst)?c[lst]:0);//表示对后边没有影响 if(dp[dep].count(st))return dp[dep][st];//开始统计 ll ans=0; if(c[0]) { c[0]--; ans+=dfs(dep+1,0); c[0]++; ans%=mod; } _f(i,1,cnt)//下一个位置放哪一类人 { if(i!=lst) { if(!c[i])continue; c[i]--; ans+=dfs(dep+1,i); c[i]++; ans%=mod; } } return dp[dep][st]=ans; } bool vis[N]; int main() { freopen("ssy.in","r",stdin); freopen("ssy.out","w",stdout); n=re(); _f(i,1,n) { a[i]=re(); } m=re(); _f(i,1,n) { a[i]%=m; if(a[i]<0)a[i]+=m;//负数的话摸出来也是负数,特殊加一下 } _f(i,1,n) { if(vis[i])continue; vis[i]=1; int ret=1; _f(j,i+1,n) { if(a[i]==a[j])vis[j]=1,ret++; } if(ret==1)c[0]++;//c[i]模数是相同的人分别有几个 else c[++cnt]=ret;//Cnt没有实际意义 mx=max(mx,ret); } fac[0]=1;ll ans=1; _f(i,1,n)fac[i]=fac[i-1]*i%mod; _f(i,0,cnt)ans=ans*fac[c[i]]%mod; ll po=dfs(1,0); ans=ans*po%mod; chu("%lld",ans); return 0; }
复制代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
T4
法一:跑最短路,处理连边的时候倒着连0,就跑出来了(非常妙!!!)
const int N=5e5+5;
int a[N];
int n,m,ee;
int tot;
struct node
{
    int to,nxt,w;
}e[N<<2];
int head[N];
inline void add(int fr,int to,int va)
{
    e[++tot].to=to,e[tot].nxt=head[fr],head[fr]=tot;e[tot].w=va;
}
queue<int>t;
int dis[N],vis[N];
void dij()//从m-->e
{
    dis[m]=0;
    t.push(m);
    int ans=inf;
    while(!t.empty())
    {
    //  chu("take out:%d\n",t.front());
        int u=t.front();
        t.pop();
        vis[u]=0;
        for(R int i=head[u];i;i=e[i].nxt)
        {
            int v=e[i].to;
            //chu("%d to%d\n",u,v);
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                if(v>ee)ans=min(ans,dis[v]);
            //  chu("dis[%d]:%d\n",v,dis[v]);
                if(!vis[v])
                t.push(v);
                vis[v]=1;
            }
        }
         
    }
     
    if(ans==inf)chu("-1");
    else chu("%d",ans);
}
int main()
{
 freopen("clean.in","r",stdin);
    freopen("clean.out","w",stdout);
memset(dis,0x7f,sizeof(dis));
    n=re(),m=re(),ee=re();
    int maxi=ee+1,mii=m;
    _f(i,1,n)
    {
        int t1=re(),t2=re(),s=re();
        add(t1,t2+1,s);
        maxi=max(maxi,max(t1,t2));
        mii=min(mii,min(t1,t2));
    }
    maxi=maxi+1;
    _f(i,mii,maxi)
    add(i,i-1,0);
    dij();
    return 0;
     
}
法二:线段树维护dp,区间最小值
f[i]=min(f[i],f[j]+cow[k])//l[k]-1<=j<=r[k]-1
 
const int N=5e5+10;
struct node
{
    int ls,rs,data;
}t[N<<4];
int tot=1;
int n,m,e;
void pushdown(int rt)
{
    if(rt)
    {
        if(!lson)t[rt].data=t[rson].data;
        else if(!rson)t[rt].data=t[lson].data;
        else t[rt].data=min(t[lson].data,t[rson].data);
    }
    return;
}
inline int merge(int rt,int l,int r,int pos,int d)
{
    if(!rt){
        rt=++tot;
        t[rt].data=inf;
    }
    if(l==r)
    {
        t[rt].data=min(t[rt].data,d);
        return rt;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)t[rt].ls=merge(lson,l,mid,pos,d);
    else t[rt].rs=merge(rson,mid+1,r,pos,d);
    pushdown(rt);
    return rt;
}
inline int query(int rt,int l,int r,int ll,int rr)
{
    if(!rt)return inf;
    if(ll<=l&&r<=rr)
    {
        return t[rt].data;
    }
    int ans=inf;
    int mid=(l+r)>>1;
    if(ll<=mid)ans=query(lson,l,mid,ll,rr);
    if(rr>mid)ans=min(ans,query(rson,mid+1,r,ll,rr));
    return ans;
}
struct node2
{
    int t1,t2,s;
    bool operator<(const node2&a)const
    {
        return t2<a.t2;
    }
}cow[N];
int f[N];
int lll=inf,rrr;
int main()
{
    freopen("clean.in","r",stdin);
    freopen("clean.out","w",stdout);
    n=re(),m=re()+2,e=re()+2;
    _f(i,1,n)
    {
        cow[i].t1=re()+2,cow[i].t2=re()+2,cow[i].s=re();
        lll=min(lll,cow[i].t1);
        rrr=max(rrr,cow[i].t2);
    }
    sort(cow+1,cow+1+n);
    _f(i,m,rrr)f[i]=inf;
    merge(1,lll-1,rrr,m-1,0);
    _f(i,1,n)
    {
        int rr=cow[i].t2,ll=cow[i].t1;
        if(ll>e||rr<m)continue;
        f[rr]=min(f[rr],query(1,lll-1,rrr,ll-1,rr-1)+cow[i].s);
        merge(1,lll-1,rrr,rr,f[rr]);
    }
    int ans=inf;
    _f(i,e,rrr)
    ans=min(ans,f[i]);
    if(ans==inf)chu("-1");
    else chu("%d",ans);
}

  

posted on   HZOI-曹蓉  阅读(219)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示