zoukankan      html  css  js  c++  java
  • 2014 ACM/ICPC Asia Regional Shanghai Online

    Tree http://acm.hdu.edu.cn/showproblem.php?pid=5044

    树链剖分,区间更新的时候要用on的左++右--的标记方法,要手动扩栈,用c++交,综合以上的条件可过。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #pragma comment(linker, "/STACK:36777216")
      5 #define mt(a,b) memset(a,b,sizeof(a))
      6 using namespace std;
      7 typedef __int64 LL;
      8 const int M=100010;
      9 struct G{
     10     struct E{
     11         int v,next;
     12     }e[M<<1];
     13     int le,head[M];
     14     void init(){
     15         le=0;
     16         mt(head,-1);
     17     }
     18     void add(int u,int v){
     19         e[le].v=v;
     20         e[le].next=head[u];
     21         head[u]=le++;
     22     }
     23 }g;
     24 int n,val[M],fa[M],dep[M],num[M],son[M],top[M],sid[M];
     25 void dfs(int u){
     26     num[u]=1;
     27     son[u]=0;
     28     for(int i=g.head[u];~i;i=g.e[i].next){
     29         int v=g.e[i].v;
     30         if(v!=fa[u]){
     31             fa[v]=u;
     32             dep[v]=dep[u]+1;
     33             dfs(v);
     34             if(num[son[u]]<num[v]) son[u]=v;
     35             num[u]+=num[v];
     36         }
     37     }
     38 }
     39 void get(int u,int Top){
     40     sid[u]=++n;
     41     top[u]=Top;
     42     if(son[u]) get(son[u],top[u]);
     43     for(int i=g.head[u];~i;i=g.e[i].next){
     44         int v=g.e[i].v;
     45         if(v!=fa[u]&&v!=son[u]){
     46             get(v,v);
     47         }
     48     }
     49 }
     50 LL lazy[M],ans[M];
     51 void query(){
     52     LL now=0;
     53     for(int i=1;i<=n;i++){
     54         now+=lazy[i];
     55         ans[i]=now;
     56     }
     57 }
     58 void update(int x,int y,int z){
     59     lazy[x]+=z;
     60     lazy[y+1]-=z;
     61 }
     62 void worknode(int x,int y,int z){
     63     int tx=top[x],ty=top[y];
     64     while(tx!=ty){
     65         if(dep[tx]<dep[ty]){
     66             swap(tx,ty);
     67             swap(x,y);
     68         }
     69         update(sid[tx],sid[x],z);
     70         x=fa[tx];
     71         tx=top[x];
     72     }
     73     if(dep[x]>dep[y]) swap(x,y);
     74     update(sid[x],sid[y],z);
     75 }
     76 void workedge(int x,int y,int z){
     77     int tx=top[x],ty=top[y];
     78     while(tx!=ty){
     79         if(dep[tx]<dep[ty]){
     80             swap(tx,ty);
     81             swap(x,y);
     82         }
     83         update(sid[tx],sid[x],z);
     84         x=fa[tx];
     85         tx=top[x];
     86     }
     87     if(x==y) return ;
     88     if(dep[x]>dep[y]) swap(x,y);
     89     update(sid[son[x]],sid[y],z);
     90 }
     91 struct IN{
     92     int type,u,v,w;
     93 }in[M];
     94 struct EDGE{
     95     int u,v;
     96 }edge[M];
     97 int main(){
     98     int t,N,m,u,v;
     99     while(~scanf("%d",&t)){
    100         int cas=1;
    101         while(t--){
    102             scanf("%d%d",&N,&m);
    103             g.init();
    104             for(int i=0;i<N-1;i++){
    105                 scanf("%d%d",&u,&v);
    106                 g.add(u,v);
    107                 g.add(v,u);
    108                 edge[i].u=u;
    109                 edge[i].v=v;
    110             }
    111             n=fa[1]=dep[1]=num[0]=0;
    112             dfs(1);
    113             get(1,1);
    114             char op[8];
    115             for(int i=0;i<m;i++){
    116                 scanf("%s%d%d%d",op,&in[i].u,&in[i].v,&in[i].w);
    117                 if(op[3]=='1') in[i].type=1;
    118                 else           in[i].type=2;
    119             }
    120             mt(lazy,0);
    121             for(int i=0;i<m;i++){
    122                 if(in[i].type&1) worknode(in[i].u,in[i].v,in[i].w);
    123             }
    124             printf("Case #%d:
    ",cas++);
    125             query();
    126             for(int i=1;i<=N;i++){
    127                 if(i>1) printf(" ");
    128                 printf("%I64d",ans[sid[i]]);
    129             }
    130             puts("");
    131             mt(lazy,0);
    132             for(int i=0;i<m;i++){
    133                 if(in[i].type==2) workedge(in[i].u,in[i].v,in[i].w);
    134             }
    135             query();
    136             for(int i=0;i<N-1;i++){
    137                 int u=edge[i].u;
    138                 int v=edge[i].v;
    139                 if(dep[u]<dep[v]){
    140                     swap(u,v);
    141                 }
    142                 if(i) printf(" ");
    143                 printf("%I64d",ans[sid[u]]);
    144             }
    145             puts("");
    146         }
    147     }
    148     return 0;
    149 }
    View Code

    Contest http://acm.hdu.edu.cn/showproblem.php?pid=5045

    根据题目要求,任意时刻都不能出现两个人做题数量的差大于1,也就是差要<=1,也就是m个问题要分成长度为n的等长的几块,每块里面一人做一个。

    问题转化为n个人n题目,如何选一种排列来获得最大价值,若暴力枚举,复杂度是10!,所以用状态压缩,降为2^10,从000推到111.

    转移时看哪个人没做过题,那么就可以让他做,状态就是他这位变为1,值就是当前状态的值加上这个人做当前的题目可获得的价值,当前的题目正好等于已做过题的人的个数+1.

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define mt(a,b) memset(a,b,sizeof(a))
     5 using namespace std;
     6 double a[16][1024],dp[1<<10];
     7 int one(int x){
     8     int res=0;
     9     while(x){
    10         if(x&1) res++;
    11         x>>=1;
    12     }
    13     return res;
    14 }
    15 int main(){
    16     int t,n,m;
    17     while(~scanf("%d",&t)){
    18         int cas=1;
    19         while(t--){
    20             scanf("%d%d",&n,&m);
    21             for(int i=0;i<n;i++){
    22                 for(int j=0;j<m;j++){
    23                     scanf("%lf",&a[i][j]);
    24                 }
    25             }
    26             int s=0,num,all=1<<n;
    27             bool flag=true;
    28             double ans=0;
    29             while(flag){
    30                 flag=false;
    31                 if(s+n<m){
    32                     flag=true;
    33                     num=n;
    34                 }
    35                 else{
    36                     num=m-s;
    37                 }
    38                 mt(dp,0);
    39                 for(int i=0;i<all;i++){
    40                     int yi=one(i);
    41                     if(yi>=num) continue;
    42                     for(int j=0;j<n;j++){
    43                         if((i>>j)&1) continue;
    44                         int next=i|(1<<j);
    45                         dp[next]=max(dp[next],dp[i]+a[j][s+yi]);
    46                     }
    47                 }
    48                 double big=0;
    49                 if(num==n){
    50                     big=dp[all-1];
    51                 }
    52                 else{
    53                     for(int i=0;i<all;i++){
    54                         if(one(i)==num){
    55                             big=max(big,dp[i]);
    56                         }
    57                     }
    58                 }
    59                 ans+=big;
    60                 s+=n;
    61             }
    62             printf("Case #%d: %.5f
    ",cas++,ans);
    63         }
    64     }
    65     return 0;
    66 }
    View Code

    Sawtooth http://acm.hdu.edu.cn/showproblem.php?pid=5047

    根据另一个类似的题目可以猜想出,这种分割方法出来的平面个数应该是个一元二次函数,a*x^2+b*x+c,过3个点,0的时候是1个平面,题目还输入两组,三个进去解出方程的abc,然后输入x就可以输出值了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define mt(a,b) memset(a,b,sizeof(a))
     4 const int M=32;
     5 class Hp { //高精度类
     6     int len,s[M];
     7 public:
     8     void init(char ch[]) {
     9         len=1;
    10         mt(s,0);
    11         int i=0;
    12         while(ch[i]=='0'&&ch[i]!=0) i++;
    13         if(ch[i]!=0) {
    14             len=strlen(ch)-i;
    15             for(i=0; i<len; i++) {
    16                 s[i]=ch[len-i-1]-48;
    17             }
    18         }
    19     }
    20     void print() { //输出
    21         int i=len-1;
    22         while(s[i]==0&&i>0) i--;
    23         for(; i>=0; i--) {
    24             printf("%d",s[i]);
    25         }
    26     }
    27     void add(int x) { //高精度加单精度
    28         int temp=0;
    29         s[0]+=x;
    30         while(s[temp]>9) {
    31             s[temp]-=10;
    32             temp++;
    33             s[temp]++;
    34         }
    35         if(s[len]!=0) len++;
    36     }
    37     void subtract(Hp a) { //高精度减高精度
    38         for(int i=0; i<len; i++) {
    39             s[i]-=a.s[i];
    40             if(s[i]<0) {
    41                 s[i]+=10;
    42                 s[i+1]--;
    43             }
    44         }
    45         while(len>1&&s[len-1]==0) len--;
    46     }
    47     void multiply(int b) { //高精度乘单精度
    48         int temp=0;
    49         for(int i=0; i<len; i++) {
    50             temp+=s[i]*b;
    51             s[i]=temp%10;
    52             temp/=10;
    53         }
    54         s[len++]=temp;
    55         while(s[len-1]>10) {
    56             s[len]+=s[len-1]/10;
    57             s[len-1]%=10;
    58             len++;
    59         }
    60         while(len>1&&s[len-1]==0) len--;
    61     }
    62     void multiply(Hp b) { //高精度乘高精度
    63         Hp c;
    64         mt(c.s,0);
    65         for(int i=0; i<len; i++) {
    66             for(int j=0; j<b.len; j++) {
    67                 c.s[i+j]+=s[i]*b.s[j];
    68                 c.s[i+j+1]+=c.s[i+j]/10;
    69                 c.s[i+j]%=10;
    70             }
    71         }
    72         len=len+b.len;
    73         for(int i=0; i<len; i++) {
    74             s[i]=c.s[i];
    75         }
    76         while(len>1&&s[len-1]==0) len--;
    77     }
    78 } A,B;
    79 char a[M];
    80 int main(){
    81     int t;
    82     while(~scanf("%d",&t)){
    83         int cas=1;
    84         while(t--){
    85             scanf("%s",a);
    86             A.init(a);
    87             B.init(a);
    88             A.multiply(B);
    89             A.multiply(8);
    90             B.multiply(7);
    91             A.subtract(B);
    92             A.add(1);
    93             printf("Case #%d: ",cas++);
    94             A.print();
    95             puts("");
    96         }
    97     }
    98     return 0;
    99 }
    View Code

     那个类似的题目被我找到了

    折线分割平面 http://acm.hdu.edu.cn/showproblem.php?pid=2050

    一样的解一元二次

     1 #include<cstdio>
     2 int main(){
     3     int t,n;
     4     while(~scanf("%d",&t)){
     5         while(t--){
     6             scanf("%d",&n);
     7             printf("%d
    ",2*n*n-n+1);
     8         }
     9     }
    10     return 0;
    11 }
    View Code

    end

  • 相关阅读:
    maven中使用命令下载指定pom.xml中的jar文件
    资源监控平台
    PerfDog的使用教程
    compile ffmepg with amr
    matplotlib
    总线通信
    阿里云NAS文件迁移项目实践
    React diff算法
    IDE Eval Resetter:JetBrains 全家桶无限试用插件
    IntelliJ IDEA 2021.2.0 官方正版
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3997021.html
Copyright © 2011-2022 走看看